结合功能(功能结合)可能是最关注的点,你开始使用Javascript,但是当你意识到你需要解决如何保持在这一功能下,你真正需要的是Function.prototype.bind(),你可能还不知道这。

当你第一次遇到这个问题,你可以设置这个变量,所以你可以继续把它换下后,许多人选择使用自我,_this,或上下文变量的名字(有些人用),这些都是有用的,当然,没问题,但有一个更好、更特别的方式去做。

我们真正需要解决的问题是什么

在下面的示例代码中,我们可以理所当然地将上下文缓存变成变量:


VaR myobj时= { {

特殊功能:功能(){

},

anotherspecialfunction:函数(){

},

getasyncdata:功能(CB){
(CB);
},

渲染:函数(){
var =;
this.getasyncdata(函数(){()
that.specialfunction();
that.anotherspecialfunction();
});
}
};

MyObj.render();




如果我们简单地使用this.specialfunction()调用的方法,我们得到下面的错误:

Uncaught TypeError:对象对象没有method'specialfunction {全球}

我们需要保持一个参考的对象的上下文myobj时回调函数的执行。打电话that.specialfunction()允许我们维护范围的背景和执行我们的功能是否正常。然而,使用Function.prototype.bind()可以有更简洁、干净的方式:


渲染:函数(){

this.getasyncdata(函数(){()

this.specialfunction();

this.anotherspecialfunction();

}绑定(这个);

}




我们刚才做了什么

绑定()创建一个函数。当函数被调用时,它的这个关键词将被设置为传入的值(这里称为当调用绑定参数())。所以,我们通过在预期的背景下,这(实际上,在myobj时)。绑定()函数,然后,当回调函数的执行,这指向myobj时对象。

如果你知道Function.prototype.bind的兴趣()是如何工作的,这是一个很简单的例子:


function.prototype.bind =功能(范围){
这个=;
返回函数(){
返回fn.apply(范围);
};
}



还有一个非常简单的用例:


var { { { {
X:3
}

函数(){()
(这console.log。x);
}

(酒吧);
未定义

无功boundfunc = bar.bind(Foo);

BoundFunc();
3


我们创建一个新函数。当它被执行时,当我们调用bar()时,它将被设置为,而不是全局范围。

浏览器支持

浏览器版本的支持

Chrome 7

火狐(火狐)4(2)

Internet Explorer 9

歌剧11.60

Safari 5.1.4

正如你所看到的,不幸的是,Function.prototype.bind是不是在IE8以下版本支持,所以如果你没有一个备份计划,可能会有问题,在运行时。

幸运的是,Mozilla开发网络(巨大资源存储库)为不实现自己的Bind()方法的浏览器提供了绝对可靠的替代方案。


如果(!函数.原型.绑定){
function.prototype.bind =功能(o){
如果(typeof这!=函数){

事情可能 / /亲密的ECMAscript 5内部iscallable功能
抛出TypeError(function.prototype.bind -什么是想肯定不是));
}

无功aargs = array.prototype.slice.call(参数1),
这ftobind =,
浮点空操作=函数(){ },
fbound =函数(){
返回ftobind.apply(这是浮点空操作流)
这
OThis,
AArgs.concat(array.prototype.slice.call(参数)));
};

fnop.prototype = this.prototype;
fbound.prototype =新的浮点空操作();

返回fbound;
};
}




适用模式



当学习技术要点时,我发现不仅有助于彻底地学习和理解概念,而且还可以了解手头是否有合适的工作地点或更接近它的地方,我希望下面的一些例子可以应用到你的代码或解决你所面临的问题上。

单击处理程序(单击处理函数)

一个目的是记录单击事件(或单击之后执行操作),这可能要求我们在对象中存储一些信息,例如:


变量记录器{ {
X:0,
updatecount:函数(){
这个,x + +;
(这console.log。x);
}
}




我们可以用下面的方法指定单击处理程序,然后调用updatecount()在记录对象的方法。


document.queryselector(按钮)。AddEventListener(听到咔哒声,函数(){(){
logger.updatecount();
});



但我们必须使该关键字在updatecount一个冗余的匿名函数()函数具有正确的价值观。

我们可以采用以下清洁方法:

document.queryselector(按钮)。AddEventListener(听到咔哒声,logger.updatecount.bind(记录器));

我们巧妙地使用了方便的Bind()函数来创建一个新函数,并将其范围绑定到一个记录器对象。

setTimeout

如果你使用一个模板引擎(如把手)或MV *(特别是使用某些帧,根据我的经验,我只能谈谈骨干。JS),所以你可能知道会遇到新的DOM节点渲染模板下面讨论的问题后,立即。

假设我们想实例化一个jQuery插件:


我想= { { var

模板:包含一个模板字符串,

美元($ # EL:内容),

afterrender:函数(){
这el.find美元('select)。MyPlugin();
},

渲染:函数(){
这el.html美元(this.template());
This.afterRender();
}
}

MyView.render();




你可能会发现它工作得很好,但不是每一次都因为有问题。这是一个竞争的问题:只有去赢得第一。有时候渲染是第一,有时插件的实例化是第一。译者注:如果绘制过程尚未完成(DOM Node尚未添加到DOM树),然后找到('select)将找不到相应的节点进行实例化。}

现在,或许没有多少人知道,我们可以使用setTimeout()通过轻微的黑客来解决问题。

我们稍微重写我们的代码,然后在DOM节点加载之后安全地实例化我们的jQuery插件:


afterrender:函数(){
这el.find美元('select)。MyPlugin();
},

渲染:函数(){
这el.html美元(this.template());
setTimeout(this.afterrender,0);
}




我们得到什么,但是,那是function.afterrender错误信息()找不到。

下一步我们要做的是在代码中使用Bind():




afterrender:函数(){
这el.find美元('select)。MyPlugin();
},

渲染:函数(){
这el.html美元(this.template());
setTimeout(this.afterrender.bind(这),0);
}





以上是本文的全部内容,希望大家能喜欢。