S6에서의 함수는 그 사용목적에 따라 세가지 종류로 명확히 구분된다.
ES6이전에는 메서드에 대한 명확한 정의없이 일반적으로 객체에 바인딩된 함수를 일컫었다.
ES6에서는 메서드 축약 표현으로 정의된 함수만을 의미한다.
const obj = {
x: 1,
foo() {
return this.x;
},
bar: function () {
return this.x;
},
};
// foo는 메서드, bar는 일반함수
ES6메서드는 non-constructor이므로 prototype프로퍼티가 없으며 프로토타입도 생성하지 않는다.
ES6메서드가 아닌 함수는 내부슬롯 [[HomeObject]] 를 갖지 않기 때문에 super키워드를 사용할 수 없다.
따라서 메서드를 정의할 때 메서드 축약 표현을 사용하는 것이 바람직하다.
ES6 메서드를 동적 추가하려면 객체 리터럴을 바인딩하고 프로토타입의 constructor 프로퍼티와 생성자 함수 간의 연결을 재설정한다.
function Person(name) {
this.name = name;
}
Person.prototype.sayHi = function () {
console.log(`Hi ${this.name}`);
};
Person.prototype = {
constructor: Person,
sayHi() {
console.log(`Hi ${this.name}`);
},
};
일반함수를 할당하는 위 방식 보다는 ES6 메서드를 할당하는 아래 방식이 바람직하다.
함수 선언문이 아닌 표현식으로만 정의할 수 있다.
const multiply = (x, y) => x * y;
multiply(2,3);
const power = x => x ** 2;
const create = (id, content) => ({ id, content });
// const create = (id, content) => { return { id, content }; }; 와 같다.
const person = ((name) => ({
sayHi() {
return `Hi My name is ${name}`;
},
}))("Lee");
console.log(person.sayHi());
this 바인딩은 함수를 정의 할 때 정해지는 것이 아니라 함수의 호출 방식에 따라 동적으로 결정된다. 일반함수를 콜백함수로 사용하는 경우 콜백함수와 일반함수의 this가 서로 다른 값을 가리킬 수 있다.
class Prefixer {
constructor(prefix) {
this.prefix = prefix;
}
add(arr) {
return arr.map(function (item) {
return this.prefix + item; // 일반함수의 this는 strict mode에서 undefined 이다.
});
}
}
const prefixer = new Prefixer('-webkit-');
console.log(prefixer.add(['transition', 'user-select']))
이와 같은 문제를 해결하기 위해 화살표 함수를 사용할 수 있다. 화살표 함수 내부에서 this를 참조하면 상위 스코프의 this를 참조한다.
class Prefixer {
constructor(prefix) {
this.prefix = prefix;
}
add(arr) {
return arr.map((item) => this.prefix + item);
}
}
const prefixer = new Prefixer("-webkit-");
console.log(prefixer.add(["transition", "user-select"]));
화살표함수가 중첩되어 있으면 화살표 함수가 아닌 가장 가까운 상위 함수를 찾는다.
화살표 함수는 자체의 this 바인딩을 가지지 않으므로 call, apply, bind 메서드를 사용해도 this를 교체할 수 없다.
this가 전역 객체로 가리키기 때문에 메서드를 화살표 함수로 정의하는 것은 피해야 한다. 메서드 축약 표현을 사용하는 것이 바람직하다.
this와 마찬가지로 화살표 함수 내부에서 this를 참조하면 상위 스코프의 super을 참조한다.
class Base {
constructor(name) {
this.name = name;
}
sayHi() {
return `Hi ${this.name}`;
}
}
class Derived extends Base {
sayHi = () => `${super.sayHi()}`; // consturctor의 super을 참조한다.
}
this와 마찬가지로 화살표 함수 내부에서 this를 참조하면 상위 스코프의 arguments을 참조한다.
(function () {
const foo = () => console.log(arguments);
foo(3, 4);
})(1, 2);
// [1, 2] , 외부함수인 즉시실행함수의 arguments를 가리킨다.
Rest 파라미터는 함수에 전달된 인수들을 목록을 배열로 전달 받는다.
function foo(...rest) {
console.log(rest);
}
foo(1, 2, 3, 4, 5); // [1, 2, 3, 4, 5]
일반 매개변수와 함께 사용할 수 있다. 단 Rest 파라미터는 할당된 인수를 제외한 나머지 인수이므로 반드시 마지막 파라미터이어야 한다.
function foo(x, y, ...rest) {
console.log(x); // 1
console.log(y); // 2
console.log(rest); // [3, 4, 5]
}
foo(1, 2, 3, 4, 5);
함수의 arguments 객체는 배열이 아닌 유사 배열 객체이다. 대신 rest 파라미터를 사용하면 배열을 직접 얻을 수 있다.
function sum(...args) {
return args.reduce((pre, cur) => pre + cur, 0);
}
console.log(sum(1, 2, 3, 4, 5)); // 15
화살표함수는 함수 자체의 arguments 객체를 갖지 않기 때문에 반드시 rest파라미터를 사용해야 한다.
ES6에서 도입된 매개변수 기본값
function sum(x = 0, y = 0) {
return x + y;
}
console.log(sum(1)); // 1
console.log(sum(1, 2)); // 3