[딥다이브] 012. es6 함수의 추가 기능
1. 함수의 구분
-
ES6 (ECMAScript 2015)
- const and let
- Default parameters(기본 매개 변수)
- Arrow functions(화살표 함수)
- Template Literals(템플릿 리터럴)
- Destructuring (구조분해할당)
- Import and export(가져오기 및 내보내기)
- Promise (프로미스)
- Rest parameter (나머지 매개 변수)
- Classes(클래스)
- Spread Opertor (전개구문 연산자)
-
ES6 이전
- 모든 함수가 callable (호출할 수 있는 함수객체)이면서 constructor(인스턴스를 생성할 수 있는 함수 객체)
- 사용목적에 따라 명확한 구분 없음
- 생성자 함수로 호출하지 않아도 프로토타입 객체 생성
-
ES6 함수
💡 `arguments` : 함수에 전달된 인수에 해당하는 `Array` 형태의 객체,
함수 내에서 이용 가능한 지역 변수
`super` : 부모 오브젝트의 함수를 호출할 때 사용
ES6 (ECMAScript 2015)
- const and let
- Default parameters(기본 매개 변수)
- Arrow functions(화살표 함수)
- Template Literals(템플릿 리터럴)
- Destructuring (구조분해할당)
- Import and export(가져오기 및 내보내기)
- Promise (프로미스)
- Rest parameter (나머지 매개 변수)
- Classes(클래스)
- Spread Opertor (전개구문 연산자)
ES6 이전
- 모든 함수가 callable (호출할 수 있는 함수객체)이면서 constructor(인스턴스를 생성할 수 있는 함수 객체)
- 사용목적에 따라 명확한 구분 없음
- 생성자 함수로 호출하지 않아도 프로토타입 객체 생성
ES6 함수
2. ES6 사양에서 메서드
💡 `프로퍼티` : 객체의 상태를 나타내는 값(data)
`메서드` : 프로퍼티(상태 데이터)를 참조하고 조작할 수 있는 동작(behavior) (딥다이브 10장)
- 메서드 축약 표현으로 정의된 함수만을 의미
- 인스턴스를 생성할 수 없는 non-constructor
const obj = {
x: 1,
// foo는 메서드입니다.
foo() {
return this.x;
},
// bar에 바인딩된 함수는 메서드가 아닌 일반 함수입니다.
bar: function () {
return this.x;
},
};
console.log(obj.foo()); // 1
console.log(obj.bar()); // 1
new obj.foo(); // TypeError: obj.foo is not a constructor
new obj.bar(); // bar {}
obj.foo.hasOwnProperty("prototype"); // false
obj.bar.hasOwnProperty("prototype"); // true
super
- ES6 메서드는 자신을 바인딩한 객체를 가리키는 내부 슬롯
[[HomeObject]]
를 가짐.
super
참조는 내부 슬롯 [[HomeObject]]
를 사용하여 수퍼클래스의 메서드를 참조하므로 내부 슬롯 [[HomeObject]]
를 갖는 ES6 메서드는 super
키워드를 사용가능.
const base = {
name: "Lee",
sayHi() {
return `Hi! ${this.name}`;
},
};
const derived = {
__proto__: base,
sayHi() {
return `${super.sayHi()}. how are you doing?`;
},
};
console.log(derived.sayHi()); // Hi! Lee. how are you doing?
3. 화살표 함수
- 화살표 함수(Arrow Function) :
function
키워드 대신 화살표(=>
, fat arrow)를 사용하여 기존의 함수 정의 방식보다 간략하게 함수를 정의함
- 표현만 간략한 것이 아니라 내부 동작도 기존의 함수보다 간략함
- 콜백 함수 내부에서
this
가 전역 객체를 가리키는 문제를 해결하기 위한 대안으로 유용
3.1. 화살표 함수 정의
함수 정의
const obj = {
x: 1,
// foo는 메서드입니다.
foo() {
return this.x;
},
// bar에 바인딩된 함수는 메서드가 아닌 일반 함수입니다.
bar: function () {
return this.x;
},
};
console.log(obj.foo()); // 1
console.log(obj.bar()); // 1
new obj.foo(); // TypeError: obj.foo is not a constructor
new obj.bar(); // bar {}
obj.foo.hasOwnProperty("prototype"); // false
obj.bar.hasOwnProperty("prototype"); // true
super
- ES6 메서드는 자신을 바인딩한 객체를 가리키는 내부 슬롯
[[HomeObject]]
를 가짐. super
참조는 내부 슬롯[[HomeObject]]
를 사용하여 수퍼클래스의 메서드를 참조하므로 내부 슬롯[[HomeObject]]
를 갖는 ES6 메서드는super
키워드를 사용가능.
const base = {
name: "Lee",
sayHi() {
return `Hi! ${this.name}`;
},
};
const derived = {
__proto__: base,
sayHi() {
return `${super.sayHi()}. how are you doing?`;
},
};
console.log(derived.sayHi()); // Hi! Lee. how are you doing?
- 화살표 함수(Arrow Function) :
function
키워드 대신 화살표(=>
, fat arrow)를 사용하여 기존의 함수 정의 방식보다 간략하게 함수를 정의함 - 표현만 간략한 것이 아니라 내부 동작도 기존의 함수보다 간략함
- 콜백 함수 내부에서
this
가 전역 객체를 가리키는 문제를 해결하기 위한 대안으로 유용
3.1. 화살표 함수 정의
함수 정의
화살표 함수는 함수 선언문으로 정의할 수 없고, 함수 표현식으로 정의해야 합니다. 호출 방식은 기존 함수와 동일합니다.
const multiply = (x, y) => x + y;
multiply(2, 3); // 6
매개변수 선언
매개변수가 여러 개인 경우 소괄호 ()
안에 매개변수를 선언합니다. 매개변수가 한 개인 경우 소괄호 ()
를 생략할 수 있습니다. 매개변수가 없는 경우 소괄호 ()
를 생략할 수 없습니다.
const arrow1 = (x, y) => { ... };
const arrow2 = x => { ... };
const arrow3 = () => { ... };
함수 몸체 정의
- 함수 몸체를 감싸는 중괄호
{}
생략 가능한 경우- 함수 몸체가 하나의 문으로 구성되었을 때
- 함수 몸체 내부의 문이 값으로 평가될 수 있는 표현식일 때
const power = (x) => x ** 2;
// const power = (x) => { return x ** 2; };
power(2); // 4
- 중괄호
{}
생략 불가능한 경우- 객체 리터럴을 반환하는 경우 소괄호
()
로 감쌈 (소괄호로 감싸지 않으면 쉼표 연산자로 잘못 해석)const create = (id, content) => ({ id, contnet }); // const create = (id, contnet) => { return { id, contnet }; }; create(1, "JavaScript"); // { id: 1, content: "JavaScript" }
- 함수 몸체가 여러개의 문으로 구성된 경우. 이 때 반환값이 있다면 명시적으로 반환
const sum = (a, b) => { const result = a + b; return result; };
- 객체 리터럴을 반환하는 경우 소괄호
- 즉시 실행함수(IIFE)로 사용가능
const person = ((name) => ({
sayHi() {
return `Hi? My name is ${name}.`;
},
}))("Lee");
console.log(person.sayHi()); // Hi? My name is Lee.
- 고차 함수(Higher-Oreder Function, HOF)에 인수로 전달가능
[1, 2, 3].map((v) => v * 2); // [2, 4, 6]
3.2. 화살표 함수와 일반 함수의 차이
- 화살표 함수는 non-constructor (인스턴스 생성 불가능)
-
prototype 프로퍼티 없음
-
프로토타입 생성하지 않음
const Foo = () => {}; Foo.hasOwnProperty("prototype"); // false
-
- 중복된 매개변수 선언 불가능
//일반함수 (strict mode가 아닐 때) function normal(a, a) { return a + a; } console.log(normal(1, 2)); // 4 //화살표함수 const arrow = (a, a) => a + a; // SyntaxError화살표 함수에서는 중복된 매개변수 이름을 선언하면 에러가 발생.
- 자체
this
,arguments
,new.target
바인딩을 갖지 않음.
내부에서 이들을 참조하면 스코프체인을 통해 상위 스코프의 식별자 참조
3.3 this
this
- 화살표 함수가 일반함수와 구별되는 가장 큰 특징
- 콜백함수 내부의
this
가 외부의 함수의this
와 달라서 생기는 문제를 해결하기 위해,
의도적으로 설계
- 콜백 함수 내부의 this문제를 방어하는 방법 : ES6이전
-
문제상황
class Prefixer { constructor(prefix) { this.prefix = prefix; } prefixArray(arr) { // ① this - 매서드를 호출한 객체(prefixer) // 인수로 전달된 배열 arr을 순회하며 배열의 모든 요소에 prefix를 추가한다. return arr.map(function (item) { return this.prefix + ' ' + item; // ② this - undefined // -> TypeError: Cannot read property 'prefix' of undefined }); } } // 출력 기대값 : ['Hello Park','Hello Lee'] const prefixer = new Prefixer('Hello'); console.log(prefixer.prefixArray(['Park', 'Lee'])); // error
-
방법 1 : 객체를 가리키는
this
를 회피시킨 후 내부에서 사용class Prefixer { constructor(prefix) { this.prefix = prefix; } add(arr) { //this를 일단 회피시킨다. const that = this; return arr.map(function (item) { return that.prefix + " " + item; }); } }
-
방법2 : Array.prototpye.map의 두번째 인수로
this
로 사용할 객체 전달class Prefixer { constructor(prefix) { this.prefix = prefix; } add(arr) { return arr.map(function (item) { return this.prefix + " " + item; }, this); } }
-
방법3 : function.prototype.bind 메서드를 사용해 호출객체를 가리키는
this
바인딩class Prefixer { constructor(prefix) { this.prefix = prefix; } add(arr) { return arr.map( function (item) { return this.prefix + " " + item; }.bind(this) ); } }
-
- 콜백 함수 내부의
this
문제를 방어하는 방법 : 화살표함수- 화살표 함수는 함수 자체의
this
바인딩을 갖지 않음 - 화살표 함수 내부에서
this
를 참조하면, 상위스코프의this
를 참조함 (Lexical this
) - 화살표 함수가 전역함수라면,
this
는 전역 객체를 가리킴 - 화살표함수와 화살표함수가 중첩되어있다면,
스코프체인 상 가장 가까운 상위함수 중 화살표함수가 아닌 함수의this
참조```jsx // 중첩 함수 foo의 상위 컨텍스트는 즉시 실행 함수이다. // 화살표 함수 foo의 this는 즉시 실행 함수의 this를 가리킨다. (function () { const foo = () => console.log(this); foo(); }).call({ a: 1 }); // { a: 1 } ```
- 화살표 함수는 함수 자체의
- 화살표함수는 this 바인딩을 갖지 않음
Function.prototype.call
,Function.prototype.apply
,Function.prototype.bind
메서드를 사용해도 화살표 함수 내부this
교체 불가window.x = 1; const normal = function () { return this.x; }; const arrow = () => this.x; console.log(normal.call({ x: 10 })); // 10 console.log(arrow.call({ x: 10 })); // 1
- 메서드를 화살표함수로 정의하는 것을 피해야함. (프로퍼티에 화살표함수 할당한 경우에도)
// 메서드를 호출한 객체를 가리키지 않고 상위 스코프의 this를 가리킴 const person = { name: "Lee", sayHi: () => console.log(`Hi, ${this.name}`), }; person.sayHi(); // Hi
- 메서드를 정의할 때 ES6메서드 축약표현으로 정의한 ES6메서드 사용
const person = { name: "Lee", sayHi(){ console.log(`Hi, ${this.name}`); } }; person.sayHi(); // Hi Lee
- 클래스 필드에 화살표 함수 할당 (클래스 필드 정의 제안 사용)
- 화살표 함수 내부에서
this
가 상위스코프의this
바인딩을 참조 - 이 때 상위 스코프는
constructor
- 클래스필드에 할당한 화살표함수 내부에서 참조하는
this
=constructor
내부의this
바인딩 = 클래스가 생성한 인스턴스 - 이 때 화살표 함수는 프로토타입 메서드가 아니라 인스턴스 메서드
class Person { name = "Lee"; sayHi = () => console.log(`Hi ${this.name}`); // constructor() { // this.name = "Lee"; // this.sayHi = () => console.log(`Hi ${this.name}`); // } } const person = new Person(); person.sayHi(); // Hi Lee
- 화살표 함수 내부에서
3.4. super
- 화살표 함수는 자체
super
바인딩을 갖지 않음 - 화살표 함수 내부에서
super
를 참조하면 상위스코프의 super를 참조//화살표함수 내부에서 super를 참조하면 constructor 내부의 super 바인딩 참조 class Base { constructor(name) { this.name = name; } sayHi() { return `Hi! ${this.name}`; } } class Derived extends Base { sayHi = () => `${super.sayHi()} how are you doing?`; } const derived = new Derived("Lee"); console.log(derived.sayHi()); // Hi! Lee how are you doing?
3.5. arguments
화살표 함수는 자체의 arguments
바인딩을 갖지않음.
따라서 화살표 함수 내부에서 arguments
를 참조하면 this
와 마찬가지로 상위 스코프의 arguments
를 참조함.
따라서 화살표 함수로 가변 인자 함수를 구현해야 할 때는 반드시 Rest 파라미터를 사용해야함.
(function () {
const foo = () => console.log(arguments); // [Arguments] { '0': 1, '1': 2 }
foo(3, 4);
})(1, 2);
4. Rest 파라미터
- Rest 파라미터(나머지 매개변수)는 매개변수 이름 앞에 세개의 점
...
를 붙여서 정의한 매개변수를 의미Rest- 파라미터는 함수에 전달된 인수들의 목록을 배열로 전달받음
function foo(...rest) {
console.log(rest); // [1, 2, 3, 4, 5]
}
foo(1, 2, 3, 4, 5);
Author And Source
이 문제에 관하여([딥다이브] 012. es6 함수의 추가 기능), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://velog.io/@ongddree/딥다이브-012.-es6-함수의-추가-기능
저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
...
를 붙여서 정의한 매개변수를 의미Rest- 파라미터는 함수에 전달된 인수들의 목록을 배열로 전달받음function foo(...rest) {
console.log(rest); // [1, 2, 3, 4, 5]
}
foo(1, 2, 3, 4, 5);
Author And Source
이 문제에 관하여([딥다이브] 012. es6 함수의 추가 기능), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@ongddree/딥다이브-012.-es6-함수의-추가-기능저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)