Modern JavaScript Deep Dive 스터디 - CH26 ES6 함수의 추가 기능
참고 자료: ⟪모던 자바스크립트 Deep Dive⟫(이웅모 지음,위키북스, 2020)
ES6 이전
: 함수는 별다른 구분 없이 다양한 목적으로 사용ES6 이후
: 사용 목적에 따라 세 가지 종류로 구분ES6 함수 종류 | constructor | protptype | super | arguments |
---|---|---|---|---|
일반 함수(Normal) | O | O | X | O |
메서드(Method) | X | X | O | O |
화살표 함수(Arrow) | X | X | X | X |
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
non-constructor
-> 생성자 함수로서 호출 불가[[HomeObject]]
(자신을 바인딩한 객체를 가리킴) 를 가짐 -> super
키워드를 사용 가능const base = {
name: "Lee",
sayHi() {
return `Hi! ${this.name}`;
},
};
const derived = {
__proto__: base,
// sayHi는 ES6 메서드다. ES6 메서드는 [[HomeObject]]를 갖는다.
// sayHi의 [[HomeObject]]는 sayHi가 바인딩된 객체인 derived를 가리키고
// super는 sayHi의 [[HomeObject]]의 프로토타입인 base를 가리킨다.
sayHi() {
return `${super.sayHi()}. how are you doing?`;
},
};
console.log(derived.sayHi()); // Hi! Lee. how are you doing?
- ES6 메서드
- 본연의 기능(
super
)를 추가- 의미적으로 맞지 않는 기능(
constructor
)은 제거- => 메서드를 정의할 때, 프로퍼티 값으로 익명 함수 표현식을 할당하는 ES6 이전의 방식은 사용하지 않는 것 권장
=>
)를 사용하여 기존의 함수 정의 방식보다 간략하게 함수를 정의this
가 전역 객체를 가리키는 문제를 해결하기 위한 대안으로 유용const multiply = (x, y) => x * y;
multiply(2, 3); // -> 6
// 매개변수가 여러개일 경우, 소괄호 안에 매개변수를 선언
const arrow = (x, y) => { ... };
// 매개변수가 한 개인 경우, 소괄호 생략 가능
const arrow = x => { ... };
// 매개변수가 없는 경우, 소괄호 생략 불가
const arrow = () => { ... };
// concise body
const power = (x) => x ** 2;
power(2); // -> 4
// 위 표현은 다음과 동일하다.
// block body
const power = (x) => {
return x ** 2;
};
const create = (id, content) => ({ id, content });
create(1, "JavaScript"); // -> {id: 1, content: "JavaScript"}
// 위 표현은 다음과 동일하다.
const create = (id, content) => {
return { id, content };
};
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.
Array.prototype.map
, Array.prototype.filter
, Array.prototype.reduce
같은 고차 함수에 인수로 전달 가능// ES5
[1, 2, 3].map(function (v) {
return v * 2;
});
// ES6
[1, 2, 3].map((v) => v * 2); // -> [ 2, 4, 6 ]
non-constructor
prototype
프로퍼티가 없고, 프로토타입도 생성하지 않음const Foo = () => {};
// 화살표 함수는 prototype 프로퍼티가 없다.
Foo.hasOwnProperty("prototype"); // -> false
this
, arguments
, super
, new.target
바인딩을 갖지 않음this
, arguments
, new.target
을 참조this
는 함수가 어떻게 호출되었는지에 따라 this
에 바인딩할 객체가 동적으로 결정this
를 참조하면 상위 스코프의 this
를 그대로 참조this
를 참조super
바인딩을 갖지 않음this
와 마찬가지로 상위 스코프에서 참조class Base {
constructor(name) {
this.name = name;
}
sayHi() {
return `Hi! ${this.name}`;
}
}
class Derived extends Base {
// 화살표 함수의 super는 상위 스코프인 constructor의 super를 가리킨다.
sayHi = () => `${super.sayHi()} how are you doing?`;
}
const derived = new Derived("Lee");
console.log(derived.sayHi()); // Hi! Lee how are you doing?
arguments
바인딩을 갖지 않음this
와 마찬가지로 상위 스코프의 arguments
를 참조rest 파라미터
를 이용function foo(...rest) {
// 매개변수 rest는 인수들의 목록을 배열로 전달받는 Rest 파라미터다.
console.log(rest); // [ 1, 2, 3, 4, 5 ]
}
foo(1, 2, 3, 4, 5);
...
을 붙여서 정의한 매개변수function foo(param, ...rest) {
console.log(param); // 1
console.log(rest); // [ 2, 3, 4, 5 ]
}
foo(1, 2, 3, 4, 5);
function bar(param1, param2, ...rest) {
console.log(param1); // 1
console.log(param2); // 2
console.log(rest); // [ 3, 4, 5 ]
}
bar(1, 2, 3, 4, 5);
function foo(...rest, param1, param2) { }
foo(1, 2, 3, 4, 5);
// SyntaxError: Rest parameter must be last formal parameter
function foo(...rest1, ...rest2) { }
foo(1, 2, 3, 4, 5);
// SyntaxError: Rest parameter must be last formal parameter
length 프로퍼티
에 영향을 주지 않음function foo(...rest) {}
console.log(foo.length); // 0
function bar(x, ...rest) {}
console.log(bar.length); // 1
function baz(x, y, ...rest) {}
console.log(baz.length); // 2
메서드
는 Rest 파라미터와 arguments 객체를 모두 사용할 수 있지만, 화살표 함수
로 가변 인자 함수를 구현해야 할 때는 반드시 Rest 파라미터를 사용undefined
function sum(x = 0, y = 0) {
return x + y;
}
console.log(sum(1, 2)); // 3
console.log(sum(1)); // 1
function foo(...rest = []) {
console.log(rest);
}
// SyntaxError: Rest parameter may not have a default initializer
length
프로퍼티와 arguments
객체에는 영향을 주지 않음function sum(x, y = 0) {
console.log(arguments);
}
console.log(sum.length); // 1
sum(1); // Arguments { '0': 1 }
sum(1, 2); // Arguments { '0': 1, '1': 2 }