帶你手動實現bind方法,讓你收穫滿滿

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;
  };
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章