[240408] ES6 함수의 추가 기능
- ES6 이전의 모든 함수는 일반 함수, 생성자, 메서드로서 호출 할 수 있었다. 사용 목적에 따라 구분 X
- 모든 함수가 callable 면서 constructor 이었음
- callable 호출할 수 있는 함수 객체
- constructor 인스턴스를 생성할 수 있는 함수 객체
- 불필요한 프로토타입 객체 생성
- ES6 에서는 함수의 목적에 따라 세 가지 종류로 구분
ES6 함수의 구분 | constructor | prototype | super | arguments |
---|---|---|---|---|
일반함수 | O | O | X | O |
메서드 | X | X | O | O |
화살표 함수 | X | X | X | X |
메서드
- ES6 사양에서 메서드는 메서드 축약 표현으로 정의된 함수만을 의미
- 이전에는 객체에 바인딩된 함수를 의미로 사용
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 임
new obj.foo(); // TypeError: obj.foo is not a constructor
new obj.bar(); // bar {}
- 인스턴스를 생성할 수 없으므로 prototype 프로퍼티가 없고, 프로퍼티타입도 생성하지 않음
obj.foo.hasOwnProperty('prototype'); // false
obj.bar.hasOwnProperty('prototype'); // true
- 참고로표준 빌트인 객체가 제공하는 프로토타입 메서드와 정적 메서드는 모두 non-constructor
- 메서드는 자인을 바인딩한 객체를 가리키는 내부 슬롯 [[HomeObject]] 가짐
- super 참조는 [[HomeObject]] 를 사용하여 수퍼 클래스의 메서드를 참조
- super 키워드 사용 가능
- ES6 메서드가 아니면 [[HomeObject]] 갖지 않음
- 메서드를 정의할 때 ES6 이전의 방식 비추 (의미적으로 맞지 않는 constructor 제거하고 super 추가 했기 때문)
화살표 함수
- 표현도 간략한데, 내부 동작도 간략함
- 콜백 함수 내부에서 this 가 전역 객체를 가리키는 문제를 해결하기 위한 대안으로 유용
1. 정의
const arrow = (x,y) => { ... };
const arrow2 = x => { ... };
const arrow3 = x => x**2;
// 객체 리터럴을 반환하는 경우 소괄호로 감싸 주어야함
const arrow4 = (id,content) => ({id, content});
2. 일반 함수와 차이
- non-constructor
- 중복된 매개변수 이름을 선언할 수 없다.
- 일반함수도 strict mode 에서는 에러 발생함
- 화살표 함수는 함수 자체의 this, arguments, super, new.target 바인딩을 갖지 않는다.
- 스코프 체인을 통해 상위 스코프 참조
- 화살표끼리 중첩되어있으면 화살표가 아닌 가장 가까운 상위 함수 중에서 참조함
3. this
- 가장 구별되는 큰 특징
- 다른 함수 인수로 전달 되는 경우가 많음
- 일반 함수는 함수를 정의할때가 아닌, 어디서 호출했냐에 따라 this 객체가 동적으로 결정된다.
class Prefixer {
constructor(prefix) {
this.prefix = prefix;
}
add(arr) {
return arr.map(function (item) {
return this.prefix + item; // this undefined 가리킴
// map 메서드가 콜백함수를 일반 함수로서 호출하기 때문
});
}
}
const prefixer = new Prefixer('-webkit-');
console.log(prefixer.add(['transition', 'user-select']));
방안
- this 를 다른 변수 값에 넣고 난 뒤 사용
- Array.prototype.map 두번째 인수로 this 전달
- prefixer 객체를 가리키는 this를 바인딩
add(arr) {
return arr.map(function (item) {
return this.prefix + ' ' + item;
}.bind(this));
- 화살표 함수 사용
화살표함수는 ?
- 함수 자체의 this 바인딩 존재 X
- 화살표 함수는 상위 스코프의 this 참조한다.
- 메서드를 화살표 함수로 정의해야하는 것은 피해야한다 ( ES6 메서드 말고 일반적인 메서드 의미)
const person = {
name: 'Lee',
sayHi: () => console.log(`Hi ${this.name}`);
// window.name 과 같음
person.sayHi(); // Hi
- 메서드를 정의할때는 ES6 메서드(축약표현)을 쓰자.
4. super
- 마찬가지로 상위 스코프의 super 참조
- super 바인딩 갖지 않는다.
- super 참조해도 에러 발생 X , constructor super 바인딩을 참조함
5. arguments
- 마찬가지로 상위 스코프의 arguments 참조
- 바인딩을 갖고 있지 않는다.
Rest 파라미터
1. 기본 문법
- … 점 세개를 붙여서 함수에 전달된 인수 목록을 배열로 전달 받음
function foo(...rest) {
// 매개변수 rest 는 인수들의 목록을 배열로 전달받는 Rest 파라미터다.
console.log(rest) // [ 1, 2, 3, 4, 5 ]
}
foo(1,2,3,4,5);
- rest 는 하나만 선언 가능
- 반드시 마지막 파라미터이어야 함
- 함수 객체의 length 에 영향을 주지 않는다.
Rest 파라미터와 arguments 객체
- arguments 객체
- 순회 가능한 유사 배열 객체
- 함수 내부에서 지역 변수처럼 사용 가능
- 배열이 아니기때문에 배열 메서드를 사용하려면 Function.prototype.call , Function.prototype.apply 메서드를 이용해 객체로 바꾸어줘야함
- rest 파라미터
- 가변 인자 하무의 인수 목록을 배열로 직접 전달 받을 수 있음
- 화살표 함수는 arguments 객체 없기때문에 rest 파라미터 이용해야함
매개변수 기본값
- ES6 에서 도입
- rest 는 기본값 지정 불가능
function sum(x=0, y=0) {
return x + y;
}
- length 프로퍼티와 arguments 객체에 영향 X
function sum(x,y=0) {
console.log(arguments);
}
console.log(sum.length); // 1
sum(1); // Argumnets {'0': 1 }
sum(1,2); // Argumnets {'0': 1, '1':2 }
Leave a comment