
별다른 구분 없이 다양한 목적으로 사용됨
ES6 이전의 모든 함수는 일반 함수로서 호출할 수 있는 것은 물론 생성자 함수로서 호출할 수 있음 ❗️
var foo = function() {
return 1;
};
foo(); // 일반 함수 : 1
new foo(); // 생성자 함수 : foo {}
var obj = { foo: foo };
obj.foo(); // 메서드 : 1
// 프로퍼티 f에 바인딩된 함수는 callable + constructor
var obj = {
x: 10,
f: function() { return this.x; }
};
// f에 바인딩된 함수를 메서드로서 호출
console.log(obj.f()); // 10
// f에 바인딩된 함수를 일반 함수로서 호출
var bar = obj.f;
console.log(bar()); // undefined
// f에 바인딩된 함수를 생성자 함수로서 호출
console.log(new obj.f()); // f {}
→ 혼란스럽고, 실수를 유발할 가능성이 있으며 성능에 좋지 않음
| ES6 함수 구분 | constructor | prototype | super | arguments |
|---|---|---|---|---|
| 일반 함수 (normal) | O | O | X | O |
| 메서드 (method) | X | X | O | O |
| 화살표 함수 (Arrow) | X | X | X | X |
일반 함수
메서드 / 화살표 함수
ES6에서의 메서드
: 메스드 축약 표현으로 정의된 함수만을 의미
ES6에서 정의한 메서드는 인스턴스를 생성할 수 없는 non-constructor
ES6 메서드는 인스턴스를 생성할 수 없으므로 prototype 프로퍼티가 없고 프로토타입도 생성하지 않음
ES6 메서드는 자신을 바인딩한 객체를 가리키는 내부 슬롯 [[HomeObject]]를 가짐
[[HomeObject]]를 사용하여 수퍼클래스의 메서드를 참조하므로 내부 슬롯 [[HomeObject]]를 갖는 ES6 메서드는 super 키워드를 사용할 수 있음[[HomeObject]]를 갖지 않기 때문에 super 키워드를 사용할 수 없음const obj = {
x: 1,
foo() { return this.x; }, // 메서드
bar: function() { return this.x; } // 일반 함수
};
console.log(obj.foo()); // 1
console.log(obj.bar()); // 1
// ES6 메서드는 인스턴스 생성 X
new obj.foo(); // TypeError: obj.foo is not a constructor
new obj.bar(); // bar {}
// ES6 메서드는 prototype 프로퍼티 X
obj.foo.hasOwnProperty('prototype'); // false
obj.bar.hasOwnProperty('prototype'); // true
화살표 함수
function 키워드 대신 화살표를 사용하여 기존의 함수 정의 방식보다 간략하게 함수를 정의하는 방법
함수 표현식으로 정의해야 함
호출 방식은 기존 함수와 동일
const multiply = (x, y) => x * y;
multiply(2, 3); // 6
const multiply = (x, y) => x * y;
multiply(2, 3); // 6
const arrow = x => {...};
const arrow = () => {...};
화살표 함수는 인스턴스를 생성할 수 없는 non-constructor
중복된 매개변수 이름을 선언할 수 없음
함수 자체의 this, arguments, super, new.target 바인딩을 갖지 않음
화살표 함수는 함수 자체의 this 바인딩을 갖지 않음
this를 참조하면 상위 스코프의 this를 그대로 참조 (lexical this)lexical this
렉시컬 스코프와 같이 화살표 함수의 this가 함수가 정의된 위치에 의해 결정된다
화살표 함수가 전역 함수라면 화살표 함수의 this는 전역 객체 ❗️
const foo = () => console.log(this);
foo(); // window
this 바인딩을 갖지 않기 때문에 Function.prototype.call, Function.prototype.apply, Function.prototype.bind를 사용해서 화살표 함수 내부의 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());
(function () {
const foo = () => console.log(arguments); // [Arguments] { '0': 1, '1': 2 }
foo(3, 4);
}(1, 2));
const foo = () => console.log(arguments);
foo(1, 2); // ReferenceError: arguments is not defined
Rest 파라미터 (나머지 매개변수)
: 매개변수 이름 앞에 세개의 점...을 붙여 정의한 매개변수
function foo(...rest){
console.log(rest); // [1, 2, 3, 4, 5]
}
foo(1, 2, 3, 4, 5);
function foo(param1, param2, ...rest){
console.log(param1); // 1
console.log(param2); // 2
console.log(rest); // [3, 4, 5]
}
foo(1, 2, 3, 4, 5);
// Rest 파라미터는 반드시 마지막 파라미터여야 함
function foo(...rest, param1, param2){}
foo(1, 2, 3, 4, 5);
// SyntaxError: Rest parameter must be last formal parameter
// Rest 파라미터는 단 하나만 선언할 수 있음
function foo(...rest1, ...rest2){}
foo(1, 2, 3, 4, 5);
// SyntaxError: Rest parameter must be last formal parameter
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
ES6 Rest 파라미터를 사용하여 가변 인자 함수의 인수 목록을 배열로 직접 전달받을 수 있음
유사 배열 객체인 arguments 객체를 배열로 변환하는 번거로움을 피할 수 있음
function sum(...args) {
return args.reduce((pre, cur) => pre + cur, 0);
}
console.log(sum(1, 2, 3, 4, 5)); // 15
함수 호출 시 매개변수의 개수만큼 인수를 전달하는 것이 바람직하지만, 그렇지 않은 경우에도 에러 발생 X
인수가 전달되지 않은 매개변수 값은 undefined
function sum(x, y) {
return x + y;
}
console.log(sum(1)); // NaN
function sum(x, y) {
x = x || 0;
y = y || 0;
return x + y;
}
console.log(sum(1, 2)); // 3
console.log(sum(1)); // 1
function sum(x = 0, y = 0) {
return x + y;
}
console.log(sum(1, 2)); // 3
console.log(sum(1)); // 1
function logName(name = 'Lee') {
console.log(name);
}
logName(); // Lee
logName(undefined); // Lee
logName(null); // null
function foo(...rest = []) {
console.log(rest);
} // SyntaxError: Rest parameter may not have a default initializer
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 }