bind() 方法建立一个新的函数,在 bind() 被调用时,这个新函数的 this 被指定为 bind() 的第一个参数,而其他参数将做为新函数的参数,供调用时使用。
从MDN对于bind的描述来看:javascript
看个例子:java
function test(name, age) { console.log(this.name); this.name = name; this.age = age; console.log(this.name, this.age); } var obj = { name: 'Willem' }; var bindFn = test.bind(obj, 'Wei'); bindFn(18); // Willem // Wei, 18
从上面的代码就能够看出来,bind函数执行以后,bindFn的this值指向了obj,而且在bind的时候传入的参数和在执行bindFn时传入的参数都成功的传入了test函数。segmentfault
那代码就呼之欲出了啊。app
Function.prototype.wbind = function() { var context = [].shift.call(arguments); var args = [].slice.call(arguments); var self = this; return function() { var innerArgs = [].slice.call(arguments); self.apply(context, args.concat(innerArgs)); } }
相关:模拟实现Javascript中的call和apply函数
既然bind返回的是一个函数,那我有一个大胆的想法,若是我把这个返回的函数做为一个构造函数会怎样呢?改造一下上面的那个例子:this
function test(name, age) { console.log(this.name); this.name = name; this.age = age; console.log(this.name, this.age); } test.prototype.sayHi = function() { console.log('Hi, ' + this.name); } var obj = { name: 'Willem' }; var bindFn = test.bind(obj, 'Wei'); var instance = new bindFn(18); // undefined // Wei,18 instance.sayHi(); // Hi, Wei console.log(obj.name); // Willem
咦,obj对象里面明明是有name属性的啊,为啥第一次输出的是undfined呢?明明传入了name属性为"Wei",为啥obj.name仍是"Willem"呢?prototype
实际上是由于this并无指向obj了,而是指向了instance
。总结一下,将返回的函数做为普通函数使用时,函数的this指向bind执行时传入的第一个参数;将返回的函数做为构造函数使用时,函数的this指向实例,而且该实例将会继承原函数原型上的属性和方法。
code
这时候,咱们再来改一改wbind函数
:对象
Function.prototype.wbind = function() { var context = [].shift.call(arguments); var args = [].slice.call(arguments); var self = this; var fBound = function() { var innerArgs = [].slice.call(arguments); // 作构造函数时,this指向实例 self.apply(this instanceof fBound ? this : context, args.concat(innerArgs)); } // 实例须要继承原函数原型上的方法和属性 // 使用fNOP中转一次是由于直接将this.prototype赋值到fNOP.prototype时 // 当修改fNOP的prototype时,this.prototype也会被修改 var fNOP = function() {} if (this.prototype) { fNOP.prototype = this.prototype; } // fBound.prototype = { __proto__: { this.prototype } } // 至关因而中间多了一个__proto__,由于原型链的缘故,因此多一层__proto__没有什么影响 fBound.prototype = new fNOP(); return fBound; }
以上,就是bind的相关内容。