ES6 이전의 함수는 일반 함수로 호출할 수 도 있고 new 연산자와 함께 생성자 함수로 호출할 수도 있다
흔히 메서드로 알고 있는 객체에 바인딩된 함수도 constructor여서 생성자 함수로 호출이 가능하다
var obj = {
x:10,
f: function(){return this.x;}
};
console.log(new obj.f()); // f {}
객체에 바인딩 된 함수가 constructor이면
그 함수 객체는 prototype 프로퍼티를 갖을 것이고
프로토타입 객체도 생성한다
콜백 함수도 constructor이기 때문에 불필요한 프로토타입 객체를 생성한다
ES6의 메서드와 화살표 함수는 non-constructor이다
ES6에서 메서드는 메서드 축약 표현으로 정의된 함수만을 의미
메서드는 prototype 프로퍼티가 없고 프로토타입 객체를 생성하지도 않는다
const obj={
x:1,
good(){ return this.x;},
bad : function(){ return this.x;}
};
new obj.good(); // 에러, good()은 메서드이므로 non-constructor
표준 빌트인 객체가 제공하는 프로토타입 메서드와 정적 메서드는 모두 non-constructor
ES6 메서드는 [[HomeObject]] 내부 슬롯을 갖는다
[[HomeObject]] 은 메서드가 정의 되어있는 객체를 가르킴
super 참조는 내부 슬롯 [[HomeObject]]를 통해 수퍼 클래스의 메서드를 참조
ES6 메서드만 super 참조 가능
const arrow = (x,y) => { ...};
const arrow = x => {...}; // 매개변수 1개면 () 생략 가능
const arrow = (x,y)=> x+y; // 함수 몸체가 표현식인 문 하나면 {} 생략 가능
const square = x => x**2; // {} 생략하고 문이 표현식이면 암묵적 반환
const square = x => {return x**2;}; // 위와 같은 코드
const arrow = () => const x = 1; // {}생략했는데 표현식이 아니면 에러,반환 불가
// 객체 리터럴을 반환하고 {} 생략할꺼면 () 로 감싸줘야한다
const create = (name,age) => ({name,age});
// {}를 객체리터럴이 아니라 코드블록으로 이해함
const create = (name,age) => {name,age};
// 함수 몸체가 여러개의 문이면 {} 생략 불가, 반환값은 명시해야함
고차 함수에 인수로 전달할 때 가독성이 좋다
콜백 함수로 정의할 때 가독성도 좋고 this도 가르키는게 없음
[1,2,3].map(x=>x*2);
class Prefixer{
constructor(prefix){
this.prefix = prefix;
}
add(arr){
return arr.map(function(item){
return this.prefix + item;
});
}
}
const prefixer = new Prefixer('my ');
console.log(prefixer.add(['house','car'])); // Error
add() 메서드 내부에서의 this는 메서드를 호출한 객체를 가르키지만
map()에 콜백 함수로 전달한 function 내부에서의 this는 일반 함수로 호출하기 때문에 전역객체를 가르킨다, 하지만 class 내부에서는 strict mode가 적용되기 때문에 undefined
이것이 바로 콜백 함수 내부의 this 문제
콜백 함수 내부의 this와 외부 함수의 this가 다르기 때문에 TypeError
class Prefixer2{
constructor(prefix){
this.prefix = prefix;
}
add(arr){
return arr.map(item => this.prefix+item);
}
}
const prefixer2 = new Prefixer2('my ');
console.log(prefixer.add(['house','car'])); // ['my house','my car']
화살표 함수는 함수 자체의 this 바인딩이 없다
즉 상위 스코프로 이동해서 this를 참조하게 된다
이것을 lexical this 라고 함
화살표 함수 안에서 this 참조 시 일반적인 식별자처럼 스코프 체인 타고 이동
const person = {
name: 'Sam',
say : ()=> console.log(`Hi i am ${this.name}`)
};
person.say(); // Hi i am
메서드를 화살표 함수로 정의하면 this는 상위 스코프에서 찾기 때문에 현재는 전역 객체를 가르킴
메서드는 ES6 메서드 축약 표현으로 정의
class Person{
name = 'Sam';
sayHi = () => console.log(`Hi i am ${this.name}`);
}
const person = new Person();
person.sayHi(); // Hi i am Sam
클래스 필드는 인스턴스의 프로퍼티이기 때문에 사실 위에 코드는 아래와 같다
class Person{
constructor(){
this.name = 'Sam';
this.sayHi = () => console.log(`Hi i am ${this.name}`);
}
}
이렇게 되면 sayHi에 할당한 화살표 함수의 상위 스코프는 constructor이기 때문에 constructor의 this인 인스턴스를 가르키게 되서 에러가 발생하지 않는 것
하지만 이렇게 하면 프로토타입 메서드가 아니라 인스턴스의 메서드이므로 Bad
메서드 축약 표현으로 정의해줘야 프로토타입 메서드가 된다
화살표 함수는 함수 자체 super 바인딩이 없다
참조시 this와 똑같이 상위 스코프 타고 올라감
class Base{
constructor(name){
this.name = name;
}
sayHi(){
return `Hi i am ${this.name}`;
}
}
class Derived extends Base{
sayHi = ()=> `${super.sayHi()} ,good to see you`
}
const derived = new Derived('Sam');
console.log(derived.sayHi()); // Hi i am Sam ,good to see you
super 참조는 원래 [[HomeObject]] 가 있는 메서드만 가능한데
화살표 함수의 super는 바인딩이 없으므로 에러나지 않고 상위 스코프인 constructor의 super바인딩을 참조함
화살표 함수는 자체 arguments 바인딩이 없다
상위 스코프로 이동해서 arguments를 찾는다
매개변수 이름 앞에 ...을 붙인 것
Rest 파라미터는 함수에 전달된 인수들을 배열로 전달 받는다
일반 매개변수와 함께 쓰면 할당하고 남은 인수들만 할당됨
가장 마지막 파라미터여야 한다
함수 객체의 length 프로퍼티(매개변수 개수)에 영향을 주지 않는다
function f(...rest){
console.log(rest);
}
f(1,2,3,4,5); // [1,2,3,4,5]
function f2(a,b,...rest){
console.log(rest)
}
f2(1,2,3,4,5); // [3,4,5]
arguments 객체는 유사 배열 객체이기 때문에 배열 메서드를 사용하려면 배열로 변환 후 해야하는 번거로움 -> Rest 파라미터
기본값은 인수를 전달하지 않았을 때, undefined를 전달 했을 때만 유효
매개변수 기본값은 함수 객체의 length프로퍼티에 영향X
function sum(x=0,y=0){
return x + y;
}
console.log(sum(1)); // x=1, y=0
sum.length; // 0
function logName(name='Sam'){
console.log(name);
}
logName(); // Sam
logName(undefined); // Sam
logName(null); // null