插曲
周末女友在家學(xué)習(xí)德玫,突然給我發(fā)了一條微信消息,打開一看是模擬實現(xiàn)bind椎麦,讓我給她講下~
講解
話不多說宰僧,開始??
第一行代碼
在函數(shù)Function的原型prototype上掛載一個bind2方法
Function.prototype.bind2 = function(context) {}
第二行代碼
把this賦值給self,主要是為后面執(zhí)行apply的時候观挎,self指向的是bind2的調(diào)用者
var self = this;
第三行代碼
使用Array.prototype.slice.call()方法把arguments這個類數(shù)組從1開始琴儿,也就是第2項到尾部的參數(shù)轉(zhuǎn)換成數(shù)組,有同學(xué)可能會疑惑為何不是第1項開始嘁捷,因為第一項一般是一個對象造成,圖中是context這個入?yún)ⅲ@個入?yún)⒃谧詈骯pply時用
其實這里的self和args在下面return的函數(shù)中用到會產(chǎn)生閉包
var args = Array.prototype.slice.call(arguments, 1);
第四行代碼
返回一個函數(shù)
return function() {}
第五行代碼
同第二行代碼類似雄嚣,這里省略沒寫第二個入?yún)⑵鋵嵤菑氖醉楅_始到末尾
var bindArgs = Array.prototype.slice.call(arguments);
第六行代碼
執(zhí)行apply方法改變函數(shù)內(nèi)this的指向到context晒屎,兩次傳入的函數(shù)的參數(shù)合并,為何要合并參數(shù)缓升,因為bind使用時首次返回的是一個函數(shù)鼓鲁,再執(zhí)行這個函數(shù),可對比apply/call的使用港谊;這里還涉及內(nèi)層函數(shù)引用外部變量坐桩,也就是經(jīng)常說的閉包。
self.apply(context, args.concat(bindArgs));
??舉個例子:
var obj = {
type: 'car'
};
function factory(brand, color) {
console.log('商品類型:', this.type) // 商品類型: car
console.log('商品品牌:', brand) // 商品品牌: BMW
console.log('商品顏色:', color) // 商品顏色: red
}
var product = factory.bind2(obj, 'BMW');
product('red')
至此封锉,講解完畢,女友表示明白了膘螟,繼續(xù)努力??
小彩蛋
? 知識點梳理:
- 原型prototype上掛載方法
- this指向
- Array.prototype.slice.call()把類數(shù)組轉(zhuǎn)成數(shù)組
- 數(shù)組concat()方法
- 閉包
- apply方法
注:bind在其他場景下的實現(xiàn)有興趣同學(xué)可再去深入探究成福。