bind方法的闡述

JavaScript中,bind() 方法夠改變對this的引用,在上下文中創建一個新函數不會被立即執行(對綁定函數的調用,並且可以指定特定的this,成爲一個新的函數,就好像是深拷貝一般),在平常工作中經常用到,並且也是面試的高熱詞彙,這裏就順帶將它進行一些解釋:

語法

fn.bind(thisArg, arg1[, arg2[, ...]]])
bind() 方法創建一個新的函數,在 bind() 被調用時,這個新函數的 this 被指定爲 bind() 的第一個參數,而其餘參數將作爲新函數的參數,供調用時使用。當使用new運算符構造,所提供的this將會被忽略,但前置參數仍會提供給模擬函數。當bind()的參數爲空時,this指向全局對象。如瀏覽器中的window。它的返回是一個原函數的拷貝,並擁有指定的 this 值和初始參數。

示例

1、在JavaScript經常犯的一個錯誤是將一個方法從對象中拿出來,然後再調用,期望方法中的 this 是原來的對象(比如在回調中傳入這個方法)。如果不做特殊處理的話,一般會丟失原來的對象。基於這個函數,用原始的對象創建一個綁定函數,巧妙地解決了這個問題:

this.x = 9;    // 在瀏覽器中,this 指向全局的 "window" 對象
var module = {
  x: 81,
  getX: function() { return this.x; }
};

module.getX(); // 81

var retrieveX = module.getX;
retrieveX();   
// 返回 9 - 因爲函數是在全局作用域中調用的

// 創建一個新函數,把 'this' 綁定到 module 對象
// 新手可能會將全局變量 x 與 module 的屬性 x 混淆
var boundGetX = retrieveX.bind(module);
boundGetX(); // 81

2、bind() 能夠使一個函數擁有預設的初始參數(默認值)。只要將這些參數作爲 bind() 的參數寫在 this 後面。當綁定函數被調用時,這些參數會被插入到目標函數的參數列表的開始位置,傳遞給綁定函數的參數會跟在它們後面(也就是說目標函數的參數會優先於調用傳遞的參數)。

function list() {
  return Array.prototype.slice.call(arguments);
}

function addArguments(arg1, arg2) {
    return arg1 + arg2
}

var list1 = list(1, 2, 3); // [1, 2, 3]

var result1 = addArguments(1, 2); // 3

// 創建一個函數,它擁有預設參數列表。
var leadingThirtysevenList = list.bind(null, 37);

// 創建一個函數,它擁有預設的第一個參數
var addThirtySeven = addArguments.bind(null, 37); 

var list2 = leadingThirtysevenList(); 
// [37]

var list3 = leadingThirtysevenList(1, 2, 3); 
// [37, 1, 2, 3]

var result2 = addThirtySeven(5); 
// 37 + 5 = 42 

var result3 = addThirtySeven(5, 10);
// 37 + 5 = 42 ,第二個參數被忽略

3、在默認情況下,使用 window.setTimeout() 時,this 關鍵字會指向 window (或 global)對象。當類的方法中需要 this 指向類的實例時,你可能需要顯式地把 this 綁定到回調函數,就不會丟失該實例的引用。

function LateBloomer() {
  this.petalCount = Math.ceil(Math.random() * 12) + 1;
}

// 在 1 秒鐘後聲明 bloom
LateBloomer.prototype.bloom = function() {
  window.setTimeout(this.declare.bind(this), 1000);
};

LateBloomer.prototype.declare = function() {
  console.log('I am a beautiful flower with ' +
    this.petalCount + ' petals!');
};

var flower = new LateBloomer();
flower.bloom();  // 一秒鐘後, 調用 'declare' 方法

4、可以通過bind實現一些共有方法。

    var fly = function(){
      //fly
      console.log('I am a ' + this.name + ', I can fly');
    };
    
    var bird = {
      name: 'bird'
    };
    var plane = {
      name: 'plane'
    };
    
    fly.bind(bird)(); //I am a bird, I can fly
    fly.bind(plane)();//I am a plane, I can fly

5、針對特定的this調用某些方法。寫起來比較麻煩,這個時候就可以使用bind創建一個shortcut方便調用。 

/*你可以用 Array.prototype.slice 來將一個類似於數組的對象(array-like object)轉換成一個真正的數組*/
var unboundSlice = Array.prototype.slice;
var slice = Function.prototype.apply.bind(unboundSlice);

// ...

slice(arguments);

參考:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章