ES5引入的函數(shù)對象的bind()方法

函數(shù)對象的bind()方法會創(chuàng)建一個新函數(shù),bind()方法返回由指定的this值和初始化參數(shù)改造的原函數(shù)拷貝。

語法 fun.bind(thisArg[, arg1[, arg2[, ...]]])

比如foo.bind(bar, arg1, arg2),它返回一個新函數(shù),就是說,內(nèi)存中出現(xiàn)了一個匿名的新函數(shù),暫且叫他newfoo吧,未來newfoo被調(diào)用的時候,它的this值指向bar的引用,newfoo的參數(shù)是foo的所有參數(shù)。

下面是一個最簡單的例子,可以看到?jīng)]啥奇怪的,this.x的this指向的是調(diào)用方法的對象,也就是module,module的x屬性的值是81,所以輸出81。

this.x = 9; 
var module = {
  x: 81,
  getX: function() { return this.x; }
};

console.log(module.getX()); // 81

然后,一個新手想把module.getX方法賦值給一個新的變量,然后打算以后用這個變量來運行function() { return this.x; },于是他寫成了:

this.x = 9; 
var module = {
  x: 81,
  getX: function() { return this.x; }
};

module.getX(); // 返回 81

var retrieveX = module.getX;
console.log(retrieveX()); // 返回 9

為什么返回9?因為var retrieveX = module.getX相當于var retrieveX = function() { return this.x; },這時候this指向window,所以返回9。

這下是不是傻逼了?怎么避免這種傻逼?給module.getX方法綁定新的this指向就可以了。

this.x = 9; 
var module = {
  x: 81,
  getX: function() { return this.x; }
};

module.getX(); // 返回 81

var retrieveX = module.getX.bind(module);
console.log(retrieveX()); // 返回 81

也就是說,retrieveX函數(shù)的this依然指向module。

bind()的另一個最簡單的用法是,使一個函數(shù)擁有預設(shè)的初始參數(shù)。這些參數(shù)(如果有的話)作為bind()的第二個參數(shù)跟在this(或其他對象)后面,之后它們會被插入到目標函數(shù)的參數(shù)列表的開始位置,傳遞給綁定函數(shù)的參數(shù)會跟在它們的后面。

比如,我們現(xiàn)有一個很簡單的做加法的函數(shù)叫foo:

function foo(a, b) {
    return a  + b;
}

我開始用這個函數(shù)解決各種問題,突然有個場景是,我已知第一個參數(shù)是41,第二個參數(shù)不確定。那么我是不是要重新寫一個幾乎一模一樣的函數(shù)呢?當然No。由于我舉例的foo函數(shù)特別簡單,你當然覺得重寫一下也不費什么勁,但如果實踐中foo函數(shù)很長很復雜呢?現(xiàn)在有bind,就可以一句創(chuàng)建出一個新函數(shù)。

function foo(a, b) {
    return a + '--' + b;
}

var bar = foo.bind(null, 41); // 第一個參數(shù)是null或者undefined的話,bar的this不改變指向,只是第一個參數(shù)永遠傳入41

console.log(bar(3)); // 41--3,第一個參數(shù)是41,第二個是3。

當然你可能說,不用bind()也可以實現(xiàn),比如下面用高階函數(shù)實現(xiàn):

function foo(a, b) {
    return a + '--' + b;
}

function bar(b) {
    return foo(41, b);
};

console.log(bar(3)); // 41--3

bind()和高階函數(shù)兩種都可以,bind()算是另一套解決方案。

現(xiàn)在我又有新要求,頁面有一個按鈕,點擊之后3秒之后打印按鈕上的文字,不注意this指向的話,會是下面這樣:

document.getElementById('btn').onclick = function() {
    var foo = function() {
        console.log(this.innerText); // undefined
    };
    setTimeout(foo, 3000);
}

怎么改?foo的bind方法傳入的第一個參數(shù)就是點擊事件的回調(diào)函數(shù),回調(diào)函數(shù)的this指向按鈕DOM對象,所以foo能輸出按鈕上的文字。

document.getElementById('btn').onclick = function() {
    var foo = function() {
        console.log(this.innerText); // undefined
    };
    setTimeout(foo.bind(this), 3000);
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容