ES6 이전의 모든 함수는 일반 함수로서 호출할 수 있는 것은 물론 생성자 함수로서 호출할 수 있었다.
(객체에 바인딩된 메서드도 일반함수 호출, 생성자 함수로 호출이 가능 등..)
하지만 이는 사용 목적에 따라 명확한 구분이 없으므로 혼란스러우며 실수를 유발 할 수 있다.
또한 콜백 함수도 불필요한 프로토타입 객체를 생성하므로 성능 면에서도 문제가 있다.
위를 해결하기 위해 사용 목적에 따라 3가지로 구분 되었다.
ES6 함수 구분 | constructor | prototype | super | arguments |
---|---|---|---|---|
일반함수 | O | O | X | O |
메서드 | X | X | O | O |
화살표 함수 | X | X | X | X |
- 일반 함수는 함수 선언문이나 함수 표현식으로 정의한 함수를 말하며 ES6 이전과 차이가 없다
- ES6의 메서드와 화살표 함수는 이전과 차이가 있다
ES6 사양에서 메서드는 메서드 축약 표현으로 정의된 함수만을 의미한다.
const obj = {
x:1,
//foo는 메서드 = non-consturctor : 인스턴스 생성 불가
foo(){return this.x}
// bar는 일반 함수
bar() : function(){return this.x}
}
// ES6 메서드는 생성자 함수로서 호출 불가
new obj.foo(); // TypeError : obj.foo is not a constructor
new obj.bar(); // bar {}
// ES6 메서드는 인스턴스를 생성할 수 없으므로 prototype 프로퍼티가 없고
// 프로토타입도 생성하지 않는다.
obj.foo.hasOwnProperty('prototype'); // false
obj.bar.hasOwnProperty('prototype'); // true
참고로 표준 빌트인 객체가 제공하는 프로토타입 메서드와
정적 메서드는 모두 non-constructor 이다.
ES6 메서드는 super 키워드를 사용할 수 있다.
즉, 자신을 바인딩한 객체를 가리키는 내부 슬롯 [[HomeObject]]를 갖는다.
이처럼 ES6 메서드는 본연의 기능 (super)을 추가하고 의미적으로 맞이 않는 기능 (constructor)은 제거 했다.
그러므로 메서드를 정의할 때 프로퍼티 값으로 익명 함수 표현식을 할당하는 ES6 이전의 방식은 사용하지 않는 것이 좋다.
화살표 함수는 함수 표현식으로 정의해야 한다. 선언문으로 정의 할 수 없다.
const mul = (x,y)=>x*y; const arrow = x=>{...}; const mul = ()=>{...}; const arrow = () => const x = 1; // SyntaxError const arrow = () => {const x = 1}; // 표현식이 아닐 땐 중괄호 생략 불가 // 객체 리터럴을 반환하는 경우 소괄호로 감싸줘야한다. const create = (id,content) => ({id,content}); // 암묵적으로 return이 붙는다. const create = (id,content) => {return {id,content};};
화살표함수와 일반함수의 차이
1. 화살표 함수는 인스턴스를 생성할 수 없는 non-constructor 다
2. 중복된 매개변수 이름을 선언할 수 없다.
3. 화살표 함수는 자체의 this, arguments, super, new.target 바인딩을 갖지 않는다.
this
자바스크립트에서 this는 함수가 호출되는 방식에 따라 동적으로 바인딩 된다.
//this는 어디서든지 참조 가능하다. //전역에서 this는 전역 객체 window를 가리킨다. console.log(this); // window function square(number) { //일반 함수 내부에서 this는 전역 객체 window를 가리킨다. console.log(this); // window return number * number; square(2); const person = { name: 'Lee', getName () { //메서드 내부에서 this는 메서드를 호출한 객체를 가리킨다. console.log(this); // {name: "Lee", getName: f} return this.name; }; console.log (person.getName ()); // Lee function Person(name) { this.name = name; //생성자 함수 내부에서 this는 생성자 함수가 생성할 인스턴스를 가리킨다. console.log(this); // Person {name: "Lee"} } const me = new Person 'Lee');
- 전역과 일반 함수 내부에서 this는 전역 객체 window를 가리킨다.
- 메서드 내부에서 this는 메서드를 호출한 객체를 가리킨다.
- 생성자 함수 내부에서 this는 생성자 함수가 생성할 인스턴스를 가리킨다.
- 화살표 함수는 함수 자체의 this 바인딩을 갖지 않으므로 함수 내부에서 this를 참조하면 상위 스코프의 this를 그대로 참조한다 (= lexical this)
- 추가적으로 super, arguments 도 상위 스코프의 super를 참조한다.
Rest 파라미터는 함수에 전달된 인수들의 목록을 배열로 전달 받는다.
function foo (...rest){ console.log(rest); //[1,2,3,4,5] } foo(1,2,3,4,5); // rest파라미터는 마지막 파라미터여야 하고 반드시 단 하나만 선언할 수 있다. function foo2 (params, ...rest){ console.log(params); // 1 console.log(rest); //[2,3,4,5] } foo2(1,2,3,4,5); // 함수 정의 시 선언한 매개변수 개수를 나타내는 length 프로퍼티에 영향을 주지 않음 function foo3 (params, ...rest){ console.log(foo3.length); // 1 } function foo4 (...rest){ console.log(foo3.length); // 0 }
화살표 함수로 가변 인자 함수를 구현해야 할 때는 반드시 Rest 파라미터를 사용해야한다.
- Rest파라미터는 인수목록을 배열로 전달 받으므로
- arguments객체는 유사 배열 객체이므로 배열 메서드 사용 시변환이 필요
function sum(...args){ return arge.reduce((pre,cur)=> pre+cur,0); } console.log(sum(1,2,3,4,5)); // 15
(단, 함수와 ES6메서드는 Rest파라미터와 arguments 객체를 모두 사용할 수 있다. )
또한 Rest 파라미터에는 기본값을 지정할 수 없다