ES6 이후 메서드

ES6 이전의 함수는 사용 목적에 따라 일반함수로 호출이 가능했고 생성자 함수로 호출이 가능했다. 즉, ES6 이전의 모든 함수는 callable이면서 constructor다.

1
2
3
[1, 2, 3].map(function (item) {
return item * 2;
}); // [ 2, 4, 6 ]
  • 심지어 콜백함수도 constructor이기 때문에 불필요한 프로토타입 객체를 생성한다.

이처럼 ES6 이전의 모든 함수는 사용 목적에 따라 명확한 구분이 없어 호출방식에 제약이 없고 생성자 함수로 호출되지 않아도 프로토타입 객체를 생성한다. 이는 혼란스러워 실수를 유발하고 성능에도 좋지 않다.

  • ES6 이후부터는 오류에 엄격하도록 만들고 있다. ⇒ 오류를 발생시킬 여지가 있는 것들은 그 부분을 개선해주고 있다.

ES6 사양에서 메서드는 메서드 축약표현으로 정의된 함수만을 의미한다.

인스턴스 생성할 수 없는 non-constructor이다.

  • 인스턴스 생성 불가
  • prototype 프로퍼티 없다
  • 프로토타입 생성 불가

ES6 메서드는 자신을 바인딩한 객체를 가리키는 내부 슬롯 [[HomeObject]]를 갖는다.

함수 사용 목적에 따라 구분한 ES6에서의 함수

이를 해결하기 위해 ES6에서는 함수를 사용 목적에 따라 3가지로 구분하였다.

ES6 함수의 구분 constructor prototype super arguments
일반함수 O O X O
메서드 X X O O
화살표 함수 X X X X

화살표 함수

function 키워드 함수보다 표현만 간단한 것이 아니라 내부 동작도 간략한다.

주로 콜백 함수 내부에서 this가 전역 객체를 가리키는 문제를 해결하기 위해 사용한다.

화살표 함수 정의

함수 선언문 안되고 함수 표현식으로만 정의 가능하다.

1
2
3
4
5
const multiply = (x, y) => x * y;

const multiply = (x) => x * y; // 매개변수 1개면 소괄호 생략 가능

const multiply = () => x * y; // 매개변수 없으면 소괄호 생략 불가

화살표 함수 몸체 정의

함수 몸체 감싸는 {} 중괄호를 생략한 경우 표현식이 아닌 문일 경우 에러를 발생 시킨다.

1
2
3
4
5
6
7
8
9
10
11
12
// concise body
const power = x => x ** 2;
power(2); // -> 4

// 위 표현은 다음과 동일하다.
// block body
const power = x => { return x ** 2; };

const arrow = () => const x = 1; // SyntaxError: Unexpected token 'const'

// 위 표현은 다음과 같이 해석된다.
const arrow = () => { return const x = 1; };

객체 리터럴을 반환하는 경우 소괄호로 감싸줘야한다.

1
2
3
4
5
6
7
const create = (id, content) => ({ id, content });
create(1, "JavaScript"); // -> {id: 1, content: "JavaScript"}

// 위 표현은 다음과 동일하다.
const create = (id, content) => {
return { id, content };
};

화살표 함수와 일반함수 차이

  1. 화살표 함수는 non-constructor로, 인스턴스 생성할 수 없다.
  • 인스턴스 생성 불가
  • prototype 프로퍼티 없다
  • 프로토타입 생성 불가
  1. 화살표 함수는 중복된 매개변수 이름 선언시 에러 발생
1
2
const arrow = (a, a) => a + a;
// SyntaxError: Duplicate parameter name not allowed in this context
  1. 화살표 함수는 this, arguments, super, new.target 바인딩 갖지 않는다.

따라서 화살표 함수 내부에서 위의 것들을 참조할 때 스코프 체인상 가장 가까운 상위 함수 중 화살표 함수가 아닌 함수의 this, arguements, super, new.target을 참조한다.

주의사항 : 메서드를 화살표 함수로 정의하지 않기

단, 메서드를 화살표 함수로 정의하면 안된다.

1
2
3
4
5
6
7
8
9
10
// Bad
const person = {
name: "Lee",
sayHi: () => console.log(`Hi ${this.name}`),
};

// sayHi 프로퍼티에 할당된 화살표 함수 내부의 this는 상위 스코프인 전역의 this가 가리키는
// 전역 객체를 가리키므로 이 예제를 브라우저에서 실행하면 this.name은 빈 문자열을 갖는
// window.name과 같다. 전역 객체 window에는 빌트인 프로퍼티 name이 존재한다.
person.sayHi(); // Hi

메서드 정의할 때는 메서드 축약 표현을 사용하는 것이 좋다.

1
2
3
4
5
6
7
8
9
// Good
const person = {
name: "Lee",
sayHi() {
console.log(`Hi ${this.name}`);
},
};

person.sayHi(); // Hi Lee
  • 메서드 내부에서 this는 메서드를 호출한 인스턴스에 바인딩된다.
1
2
3
4
5
6
7
8
9
10
// Bad
function Person(name) {
this.name = name;
}

Person.prototype.sayHi = () => console.log(`Hi ${this.name}`);

const person = new Person("Lee");
// 이 예제를 브라우저에서 실행하면 this.name은 빈 문자열을 갖는 window.name과 같다.
person.sayHi(); // Hi
  • 프로토타입 객체의 프로퍼티에 화살표 함수를 사용하는 것도 문제가 된다.
  • 프로퍼티 동작 추가 시에는 ES6 메서드 정의 사용할 수 없으므로 일반함수로 정의해야한다.