显式绑定
如果我们不想像隐式绑定一样,在一个对象内部包含一个函数引用,而是像在某个对象上强制调用函数,需要怎么做呢?
js中“所有”函数都有一些有用的特性(这和它们的[[Prototype]])有关,可以被用于解决这个问题:
具体来说,可以使用函数的call和apply方法。
这两个方法的第一个参数是一个对象,是给this准备的,接着在调用函数时将其绑定到this。因为可以直接指定this绑定的对象,因此我们称之为显式绑定。
function foo(){
console.log(this.a);
}
var obj={
a:2
};
foo.call(obj);
通过call,我们可以在调用foo时强制把它的this绑定到obj上。
如果传入的是原始值(字符串类型,布尔类型或者数字类型)来当作this绑定对象,这个原始值会被转换成它的对象形式(也就是new String(..),new Boolean(..)或者new Number(..))。这通常被称为“装箱”
从this绑定的角度来说,call和apply是一样的。
显式绑定仍然无法解决之前的丢失绑定的问题。
硬绑定
显式绑定的一个变种->硬绑定,可以解决这个问题。
function foo(){
console.log(this.a);
}
var obj={
a:2
};
var bar=function(){
foo.call(obj);
};
bar();//2
setTimeout(bar,100);//2
//硬绑定的bar不可能再修改它的this
bar.call(window);
我们创建啦函数bar(),并在它的内部手动调用foo.call(obj),因此强制把foo的this绑定到了obj,无论之后如何调用函数bar;它总会手动在obj上调用foo,这是一种显式的强制绑定,称之为硬绑定。
由于硬绑定是一种常用的模式,所以ES5提供了内置的方法Function.prototype.bind
用法如下:
function foo(){
console.log(this.a);
}
var obj={
a:2
};
var bar=foo.bind(obj);
bar();
第三方库的许多函数,以及js语言和宿主环境中许多新的内置函数,都提供了一个可选的参数,通常被称为“上下文”
其作用和bind一样,确保回调函数使用指定的this
比如:
function foo(el){
console.log(el,this.id);
}
var obj={
id:"awesome"
};
var temp=[1,2,3];
temp.forEach(foo,obj);
function foo(el){
console.log(el,this.id);
}
var obj={
id:"awesome"
};
var temp=[1,2,3];
temp.forEach(foo,obj);