ES6 (ECMAScript 2015)
ES6 이전
ES6 함수
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
[[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?
function
키워드 대신 화살표(=>
, fat arrow)를 사용하여 기존의 함수 정의 방식보다 간략하게 함수를 정의함this
가 전역 객체를 가리키는 문제를 해결하기 위한 대안으로 유용화살표 함수는 함수 선언문으로 정의할 수 없고, 함수 표현식으로 정의해야 합니다. 호출 방식은 기존 함수와 동일합니다.
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;
};
const person = ((name) => ({
sayHi() {
return `Hi? My name is ${name}.`;
},
}))("Lee");
console.log(person.sayHi()); // Hi? My name is Lee.
[1, 2, 3].map((v) => v * 2); // [2, 4, 6]
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
바인딩을 갖지 않음.this
this
가 외부의 함수의 this
와 달라서 생기는 문제를 해결하기 위해,문제상황
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 }
```
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
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
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?
화살표 함수는 자체의 arguments
바인딩을 갖지않음.
따라서 화살표 함수 내부에서 arguments
를 참조하면 this
와 마찬가지로 상위 스코프의 arguments
를 참조함.
따라서 화살표 함수로 가변 인자 함수를 구현해야 할 때는 반드시 Rest 파라미터를 사용해야함.
(function () {
const foo = () => console.log(arguments); // [Arguments] { '0': 1, '1': 2 }
foo(3, 4);
})(1, 2);
...
를 붙여서 정의한 매개변수를 의미Rest- 파라미터는 함수에 전달된 인수들의 목록을 배열로 전달받음function foo(...rest) {
console.log(rest); // [1, 2, 3, 4, 5]
}
foo(1, 2, 3, 4, 5);