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的相關內容。