자동으로 부여되는 상황별 this규칙을 깨고 명시적으로 this를 지정하려면
call / apply / bind 를 함께 사용하면 된다.
기존에 있었던 메서드 뒤에 붙어서 즉시 실행해주되
명시적으로 binding할 객체(this로 지정할 객체)를 뒤에 써줘야 함.
call 메서드와 완전히 동일.
but! this에 binding할 객체는 똑같이 넣어주고 나머지 부분만 배열 형태로 넘겨줌.
1) 유사배열객체(array-like-object)에 배열 메서드를 적용
2) Array.from 메서드(ES6)
3) 생성자 내부에서 다른 생성자를 호출(공통된 내용의 반복 제거)
4) 여러 인수를 묶어 하나의 배열로 전달할 때 apply 사용 가능
//apply는 (this로 엮을 인자, 배열)을 받아야 함, 일부러 this를 안 넣겠다 해서 null
var numbers = [10, 20, 3, 16, 45];
var max = Math.max.apply(null, numbers);
var min = Math.min.apply(null, numbers);
console.log(max, min);
call과는 다르게 즉시 호출하지는 않고 넘겨받은 this 및 인수들을 바탕으로
새로운 함수를 반환하는 메서드
함수에 this를 미리 적용하고 부분 적용 함수 구현할 때 용이함.
var func = function (a, b, c, d) {
console.log(this, a, b, c, d);
};
func(1, 2, 3, 4); // this는 window객체
// 함수에 this 미리 적용
var bindFunc1 = func.bind({ x: 1 }); // 바로 호출되지는 않아요! 그 외에는 같아요.
bindFunc1(5, 6, 7, 8); // { x: 1 } 5 6 7 8
// 부분 적용 함수 구현
var bindFunc2 = func.bind({ x: 1 }, 4, 5); // 4와 5를 미리 적용
bindFunc2(6, 7); // { x: 1 } 4 5 6 7
bindFunc2(8, 9); // { x: 1 } 4 5 8 9
++ bind 메서드 활용) 상위 컨텍스트의 this를 내부함수나 콜백 함수에 전달
var obj = {
outer: function() {
console.log(this);
var innerFunc = function () {
console.log(this); //{ outer: [Function: outer] }출력
}.bind(this); // innerFunc에 this를 결합한 새로운 함수를 할당
innerFunc();
}
};
obj.outer(); //{ outer: [Function: outer] }출력
화살표 함수는 실행 컨텍스트 생성 시, this를 바인딩하는 과정이 제외
스코프체인상 가장 가까운 this에 접근하고 this우회, call, apply, bind보다 편리한 방법
1) obj늪..
🤔--> obj1.outer(); 에 의해서 2번째줄 실행 -> console.log(this);에서 this가 처음으로 호출되고 그 호출의 주체 객체 obj1가 찍힌 거까지는 알겠는데...
왜 { outer: [function: outer]} 이 찍혔지 {outer: fun} 이 아니라?
아님 {outer: fun()}로 찍히던가
왜 굳이 저 fun () 안에 outer가 들어갔을까
여기저기 떠들어 봤지만 해결을 못했다..
🤔-->여기도 마찬가지. 굳이 function가 써진 이유는..?
2) bind를 써서 상위 컨텍스트의 this를 콜백 함수에 전달할 수 있는데
setTimeout이라는 함수의 첫 등장과 함께 콜백함수의 개념이 혼란의 카오스를 만들었다..
🤔 가운데 setTimeout(this.logThis, 500); 가 실행되었을 때 obj라는 주체 설정까지 해줬는데
왜 자꾸 this가 전역 객체를 참조해 정상동작하지 않는지 이해가 되지 않았다.
📌 애초에 obj.logThisLater1();에서 지정해준 Obj라는 주체는
this.logThis 함수가 실행되었을 때 그냥 인용된 것이지
그 안에 결과값인 console.log(this)의 this는 될 수 없는 거였다.
즉 this가 지정되지 않은 상태! 그래서 this가 전역 객체를 참조에 결과가 그렇게 나온 것
반면 obj.logThisLater2(); 결과값은 binding을 해줬기 때문에
setTimeout(this.logThis.bind(this), 1000);가 실행되면
1초를 뒤 아래와 같이 정상동작하여 출력된다.
{
logThis: [Function: logThis],
logThisLater1: [Function: logThisLater1],
logThisLater2: [Function: logThisLater2]
}
bind를 쓰면 상위 컨텍스트의 this를 내부함수나 콜백 함수에 전달할 수 있어 좋은데
그 상위 컨텍스트가 무엇인지, 그 컨텍스트의 this는 무엇인지 제대로 파악하는 게
아주 중요한 것 같다..
📌 콜백함수
다른 코드의 인자로 넘겨주는 함수
다른 코드(함수 또는 메서드)에게 인자로 넘겨줌으로써 그 제어권도 함께 위임
setTimeout 함수는
콜백 함수를 호출할 때(위에서는 this.logThis) 대상이 될 this를 지정하지 않으면
this는 곧 window객체!
왜? 콜백 함수도 함수이기 때문에 기본적으로 this가 ‘전역 객체’를 참조
🔥 예외! 제어권을 넘겨받을 코드에서
콜백 함수에 별도로 this가 될 대상을 지정한 경우에는 그 대상을 참조한다.