다음 규칙은 명시적인 this 바인딩이 없는 한 늘 성립한다.
Function.prototype.call(thisArg[, arg1[, arg2[, ...]]])
call 메서드는 메서드의 호출 주체인 함수를 즉시 실행하도록 하는 명령입니다. 이때 call메서드의 첫 번째 인자를 this로 바인딩하고, 이후의 인자들을 호출할 함수의 매개변수로 합니다. 함수를 그냥 실행하면 this는 전역객체를 참조하지만 call 메서드를 이용하면 임의의 객체를 this로 지정할 수 있습니다.
var func = function (a, b, c) {
console.log(this, a, b, c);
};
func(1, 2, 3); // window( ... ) 1 2 3
func.call({ x : 1}, 4, 5, 6); // { x: 1} 4 5 6
Function.prototype.apply(thisArg[, argsArray])
apply 메서드는 call 메서드와 기능적으로 완전히 동일합니다.
call 메서드는 첫 번째 인자를 제외한 나머지 모든 인자들을 호출할 함수의 매개변수로 지정하는 반면,
apply 메서드는 두 번째 인자를 배열로 받아 그 배열의 요소들을 호출할 함수의 매개변수로 지정한다는 점에서만 차이가 있습니다.
var func = function (a, b, c) {
console.log(this, a, b, c);
};
func.apply({x: 1}, [4, 5, 6]); // {x: 1}, 4, 5, 6
var obj = {
a: 1,
method: fuction(x, y) {
console.log(this.a, x, y);
}
};
obj.method.apply({ a:4 }, [5, 6]); // 4 5 6
Function.prototype.bind(thisArg[, arg1[, arg2[, ...]]])
bind 메서드는 ES5에서 추가된 기능으로, call과 비슷하지만 즉시 호출하지는 않고 넘겨받은 this 및 인수들을 바탕으로 새로운 함수를 반환하기만 하는 메서드입니다.
다시 새로운 함수를 호출할 때 인수를 넘기면 그 인수들을 기존 bind 메서드를 호출할 때 전달했던 인수들의 뒤에 이어서 등록됩니다.
즉 bind 메서드는 함수에 this를 미리 적용하는 것과 부분 적용 함수를 구현하는 두 가지 목적을 모두 지닙니다.
var func = function (a, b, c, d) {
console.log(this, a, b, c, d);
};
func(1, 2, 3, 4); // window{ ... } 1 2 3 4
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);
bindFunc2(6, 7) // { x: 1} 4 5 6 7
bindFunc2(8, 9) // { x: 1} 4 5 8 9
var obj = {
outer: function () {
console.log(this);
var innerFunc = function () {
console.log(this);
};
innerFunc.call(this);
}
};
obj.outer();
var obj = {
outer: function () {
console.log(this);
var innerFunc = function () {
console.log(this);
}.bind(this);
innerFunc();
}
};
obj.outer();
var obj = {
logThis: function () {
console.log(this);
},
logThisLater1: function () {
setTimeout(this.logThis, 500);
},
logThisLater2: function () {
setTimeout(this.logThis.bind(this), 1000);
}
};
obj.logThisLater1(); // window { ... }
obj.logThisLater2(); // obj { logThis: f, ...}
};