1.手動實現bind方法的要點
- 當作爲this參數傳入的值爲原始類型數據時,該數據會被包裝成對象。傳入null或者undefined時,this會被替換爲window。
- 傳入一般對象時,返回的函數內部this指向該對象。
- bind方法一個經典用法就是偏函數的應用。讓函數可以擁有預設參數。
- 最重要的一點就是綁定函數作爲構造函數去調用。MDN:綁定函數自動適應於使用 new 操作符去構造一個由目標函數創建的新實例。當一個綁定函數是用來構建一個值的,原來提供的 this 就會被忽略。不過提供的參數列表仍然會插入到構造函數調用時的參數列表之前。
意思就是:當綁定函數作爲構造函數去調用的時候,它被提供的this會被忽略掉。然後,就會像一般的構造函數一樣去新建對象實例了。
示例:
const obj = {
name: 'ha'
}
function Student(name){
this.name = name;
}
const newS = Student.bind(obj, 23); // obj被忽略
const newObj = new newS(1);
console.log(obj); // {name: "ha"} obj的name屬性值並未被改變
console.log(newObj); // Student {name: 23}
如果不用new操作構造函數去生成對象實例的話,那麼提供的this參數就會生效。
const obj = {
name: 'ha'
}
function Student(name){
this.name = name;
}
const newS = Student.bind(obj, 23); // obj的name屬性會被改變
const newObj = newS(1); // 去掉了new操作符
console.log(obj); // {name: 23} obj的name屬性值並未被改變
console.log(newObj); // undefined
2.手動實現bind方法
// 手動實現bind方法
// MDN:關於綁定函數,做了如下說明:指的是某一函數(目標函數)調用了bind()方法後,原地生成的函數,爲綁定函數。
Function.prototype.myBind = function (context, ...args) {
const self = this;
// 最重要的是返回一個函數
context = [null, undefined].includes(context) ? window : {
number: new Number(context),
boolean: new Boolean(context),
string: new String(context)
}[typeof context];
const fBound = function() {
// 這裏不要忘了加上return
// 另外,就是如果new了綁定函數,那麼傳遞給目標函數的this,即context參數就被忽略。否則,生效。
return self.apply(this instanceof fBound ? this : context || window, args.concat(Array.prototype.slice.call(arguments)));
}
fBound.prototype = Object.create(self.prototype); // new出來的實例的原型,應爲目標函數的原型
return fBound;
};