深入理解JS中的Function.prototype.bind()方法
前言
對于函數綁定(Function binding)很有可能是大家在使用JavaScript時最少關注的一點,但是當你意識到你需要一個解決方案來解決如何在另一個函數中保持this上下文的時候,你真正需要的其實就是 Function.prototype.bind() ,只是你有可能仍然沒有意識到這點。
第一次遇到這個問題的時候,你可能傾向于將this設置到一個變量上,這樣你可以在改變了上下文之后繼續(xù)引用到它。
一. bind的語法
bind() 方法的主要作用就是將函數綁定至某個對象,bind() 方法會創(chuàng)建一個函數,函數體內this對象的值會被綁定到傳入bind() 函數的值。
1.1 定義
bind()的定義如下:
The bind() method creates a new function that, when called, has its this keyword set to the provided value, with a given sequence of arguments preceding any provided when the new function is called.
bind() 函數會創(chuàng)建一個新函數(稱為綁定函數),新函數與被調函數(綁定函數的目標函數)具有相同的函數體。當目標函數被調用時 this 值綁定到 bind() 的第一個參數,該參數不能被重寫。
1.2 原理
可以用如下代碼模擬bind()的原理:
Function.prototype.bind = function(context) {
var self = this; // 保存原函數
return function() { // 返回一個新函數
return self.apply(context, arguments); // 執(zhí)行新函數時,將傳入的上下文context作為新函數的this
}
}
1.3 語法
Function.prototype.bind(thisArg[, arg1[, arg2[, ...]]])
二. bind的應用場景
2.1 實現(xiàn)對象繼承
var A = function(name) {
this.name = name;
}
var B = function() {
A.bind(this, arguments);
}
B.prototype.getName = function() {
return this.name;
}
var b = new B("hello");
console.log(b.getName()); // "hello"
2.2 事件處理
var paint = {
color: "red",
count: 0,
updateCount: function() {
this.count++;
console.log(this.count);
}
};
// 事件處理函數綁定的錯誤方法:
document.querySelector('button')
.addEventListener('click', paint.updateCount); // paint.updateCount函數的this指向變成了該DOM對象
// 事件處理函數綁定的正確方法:
document.querySelector('button')
.addEventListener('click', paint.updateCount.bind(paint)); // paint.updateCount函數的this指向變成了paint
2.3 時間間隔函數
var notify = {
text: "Hello World!",
beforeRender: function() {
alert(this.text);
},
render: function() {
// 錯誤方法:
setTimeout(this.beforeRender, 0); // undefined
// 正確方法:
setTimeout(this.beforeRender.bind(this), 0); // "Hello World!"
}
};
notify.render();
2.4 借用Array的原生方法
var a = {};
Array.prototype.push.bind(a, "hello", "world")();
console.log(a); // "hello", "world"
三. bind()方法的瀏覽器兼容性

四. bind()的兼容性寫法
if (!Function.prototype.bind) {
Function.prototype.bind = function() {
var self = this, // 保存原函數
context = [].shift.call(arguments), // 需要綁定的this上下文
args = [].slice.call(arguments); // 剩余的參數轉成數組
return function() { // 返回一個新函數
// 執(zhí)行新函數時,將傳入的上下文context作為新函數的this
// 并且組合兩次分別傳入的參數,作為新函數的參數
return self.apply(context, [].concat.call(args, [].slice.call(arguments)));
}
};
}
五. bind與 call/apply方法的區(qū)別
共同點:
都可以改變函數執(zhí)行的上下文環(huán)境;
不同點:
bind: 不立即執(zhí)行函數,一般用在異步調用和事件; call/apply: 立即執(zhí)行函數。
總結
好了,以上就是這篇文章的全部內容了,希望本文的內容對大家學習或者使用Javascript能有一定的幫助,如果有疑問大家可以留言交流。
- javascript使用eval或者new Function進行語法檢查
- eval(function(p,a,c,k,e,d)系列解密javascript程序
- js eval函數使用,js對象和字符串互轉實例
- js中的eval()函數把含有轉義字符的字符串轉換成Object對象的方法
- AngularJs $parse、$eval和$observe、$watch詳解
- 關于動態(tài)執(zhí)行代碼(js的Eval)實例詳解
- JS使用eval()動態(tài)創(chuàng)建變量的方法
- javascript中JSON.parse()與eval()解析json的區(qū)別
- 深入淺析JSON.parse()、JSON.stringify()和eval()的作用詳解
- JS中Eval解析JSON字符串的一個小問題
- 詳解Vue.js搭建路由報錯 router.map is not a function
- 淺談js中function的參數默認值
- 淺析JS中對函數function的理解(基礎篇)
- JS中注入eval, Function等系統(tǒng)函數截獲動態(tài)代碼
相關文章
深入理解JavaScript系列(48):對象創(chuàng)建模式(下篇)
這篇文章主要介紹了深入理解JavaScript系列(48):對象創(chuàng)建模式(下篇),本篇主要是介紹創(chuàng)建對象方面的模式的下篇,利用各種技巧可以極大地避免了錯誤或者可以編寫出非常精簡的代碼,需要的朋友可以參考下2015-03-03
javascript使用window.open提示“已經計劃系統(tǒng)關機”的原因
這篇文章主要介紹了javascript使用window.open提示“已經計劃系統(tǒng)關機”的原因,本文得出結論是安裝了系統(tǒng)更新或其它原因,要把系統(tǒng)重啟時才會提示這個問題,所以,遇到這個問題,重啟你的電腦吧2014-08-08
javascript代碼運行不出來執(zhí)行錯誤的可能情況整理
js代碼運行不出來的情況在項目中經常發(fā)生,究竟是什么原因呢?在本文整理了一些常見的情況,感興趣的各位朋友可以參考下2013-10-10
JavaScript開發(fā)規(guī)范要求(規(guī)范化代碼)
作為一名開發(fā)人員(WEB前端JavaScript開發(fā)),不規(guī)范的開發(fā)不僅使日后代碼維護變的困難,同時也不利于團隊的合作,通常還會帶來代碼安全以及執(zhí)行效率上的問題。2010-08-08

