理解建议:若是对this指向规则不了解的话,建议先了解this指向规则,最好还能对call和apply的使用和内部原理也有所了解,否则直接研究bind仍是会有些难度的。html
//html <button id="btn"></button> //js var list = { init:function(){ this.ms = "duyi"; this.dom = document.getElementById("btn"); this.bindEvent(); }, bindEvent:function(){ this.dom.onclick = this.showMessage.bind(this); }, showMessage:function(){ alert(this.ms); } } list.init();
在单对象编程中,有一种很是典型的bind()的应用,就以上面的示例来讲,当出现给DOM绑定事件回调函数时,又还须要继续保持函数的this指向原来的对象,就能够按照示例的这种方式来实现:this.dom.onclick = this.showMessage.bind(this);编程
咱们知道call和apply能够改变函数执行的this指向,可是call和apply都是当即执行该函数,而bind是将this指向绑定到指定的对象上,而且返回函数并维持this指向这个对象。接下来再来看看bind的参数设置示例:app
function show(x,y,z,w){ console.log(this,x,y,z,w); } var DuyiO = { x : 20 } var newShow = show.bind(DuyiO,"1","2",3); newShow(4);//Object {x: 20} "1" "2" 3 4
bind的参数和call很是相似,惟一的区别就在于除了调用bind时传入参数外,还能够在正式执行时传入参数,两次传入参数以拼接的方式做为函数执行的实参。可是须要注意的是,第一个参数做为函数的this指向对象必需要在调用bind方法时传入,若是调用bind方法不传入任何参数,函数的this指向就会绑定到window上。好比下面这种状况:dom
var newShow = show.bind(); newShow(DuyiO,"1","2",3,4);//Window {…} Object {x: 20} "1" "2" 3
最后还有一个基本上不会被应用到的功能,就是返回的函数被new关键字用来建立一个新的对象,而构造函数仍是原函数自己(第二个示例中的show)。这个功能在模仿bind源码不能100%实现,可是也能够间接的实现其须要的功能。函数
1.首先实现函数调用bind修改this指向即参数设置:this
1 Function.prototype.MyBind = function(target){ 2 var self = this; 3 var args = [].slice.call(arguments,1); 4 var f = function(){ 5 return self.apply( target || window,args ); 6 } 7 return f; 8 }
2.接着再来实现函数正式调用执行时传入设置:spa
1 Function.prototype.MyBind = function(target){ 2 var self = this; 3 var args = [].slice.call(arguments,1); 4 var f = function(){ 5 var _arg = [].slice.call(arguments,0); 6 return self.apply( target || window,args.concat(_arg) ); 7 } 8 return f; 9 }
3.最后实现当返回函数被new操做符引用做为构造函数依然指向原函数(模拟实现功能):prototype
1 Function.prototype.MyBind = function(target){ 2 var self = this; 3 var args = [].slice.call(arguments,1); 4 var temp = function(){}; 5 var f = function(){ 6 var _arg = [].slice.call(arguments,0); 7 return self.apply(this instanceof temp ? this : ( target || window ),args.concat(_arg) ); 8 } 9 temp.prototype = self.prototype; 10 f.prototype = new temp(); 11 return f; 12 }
这个模拟实现主要有两个关键点须要重点理解:code
a.代码第七行中的this instanceof temp ? this : ( target || window ):当返回函数f被new做为构造函数引用时,这时候this指向了函数执行时内部隐式添加在变量对象上的this(这里不清楚的话能够参考JavaScript中的this指向规则),固然普通调用执行就是指向self。htm
b.代码第九行和第十行为何须要改变f的原型,这就是我前面讲的模拟实现方法构造,咱们知道bind在JS内部实现的是其返回函数仍是那个原来的函数,这里咱们多加了一层f来实现的,因此在函数被当作构造函数的时候,将f的原型指向self也能够实现其功能,可是构造的实例对象是基于f实现的,最终构造原型链仍是指向self原型,该有的方法属性依然都会有。只是在原型链上多了f这个包装层。