示例代碼
var thisArg = {};
function targetFunc( arg1, arg2, arg3 ) {
console.log( this === thisArg );
}
var boundFunc = targetFunc.bind( thisArg, 1, 2 );
// thisArg
boundFunc(); // true
// function name
console.log( targetFunc.name ); // targetFunc
console.log( boundFunc.name ); // bound targetFunc
// the typical number of arguments expected by the function
console.log( targetFunc.length ); // 3
console.log( boundFunc.length ); // 1
以上述代碼為示例,boundFunc 和 targetFunc 的關(guān)系:
基礎(chǔ)
- 調(diào)用 boundFunc 函數(shù)就像調(diào)用 targetFunc 函數(shù)一樣蒸苇,只是 boundFunc 內(nèi)部的 this 指向 thisArg。
- boundFunc 的名字是 targetFunc 函數(shù)的名字加上前綴:bound缘厢。
- boundFunc 形參數(shù)量(boundFunc.length)是 targetFunc 形參數(shù)量減去調(diào)用 targetFunc.bind( thisArg, 1, 2 ) 時候輸入的參數(shù)的數(shù)量台谍。如果調(diào)用 bind 時輸入的參數(shù)數(shù)量大于 targetFunc 的形參數(shù)量,則 boundFunc 的形參數(shù)量為 0(boundFunc.length === 0)匹涮。
function tf( arg1, arg2, arg3 ) {
}
var bf = tf.bind( null, 1, 2, 3, 4, 5 );
console.log( bf.length ); // 0
高級
bind 返回的 boundFunc 其實不是一般的對象(在 js 中天试,函數(shù)也是一個對象),在規(guī)范中稱之為 exotic object然低,而一般的函數(shù)在規(guī)范中稱之為 ordinary object喜每。區(qū)別在于 exotic object 可能沒有 ordinary object 一些通用的內(nèi)部屬性(internal slot)务唐。譬如:一般的函數(shù)對象有一個內(nèi)部屬性[[Strict]]
,標(biāo)識這個函數(shù)是否運行在嚴(yán)格模式下带兜,而 boundFunc 沒有枫笛。但是 boundFunc 有如下一些特殊的內(nèi)部屬性:
-
[[BoundTargetFunction]]
:被包裝的函數(shù),即上例中的 targetFunc刚照。 -
[[BoundThis]]
:targetFunc 每次被調(diào)用時刑巧,this 指向的那個值,即上例中的 thisArg涩咖。 -
[[BoundArguments]]
:一個列表海诲,當(dāng) targetFunc 被調(diào)用時候先傳入的參數(shù)們,即上例中的 1檩互,2特幔。
然后運行 boundFunc( argumentsList ) 的過程基本上概括為:
// 假設(shè) argumentsList 是 boundFunc 被調(diào)用時傳入的參數(shù)列表
var argumentsList;
var target = boundFunc.[[BoundTargetFunction]];
var boundThis = boundFunc.[[BoundThis]];
var boundArgs = boundFunc.[[BoundArguments]];
// boundArgs 和 argumentsList 都不是 js array,但是這里作為示例偽代碼 就懶得做轉(zhuǎn)換了闸昨。
var args = boundArgs.concat( argumentsList );
target.apply( boundThis, args );
后記
看了一遍 Function.prototype.bind 的規(guī)范蚯斯,發(fā)現(xiàn)沒有什么特別的邊際條件,倒是又引出了兩個主題:函數(shù)作為普通函數(shù)和構(gòu)造函數(shù)分別是如何運行饵较。(接下來準(zhǔn)備為這兩個主題分別總結(jié)下拍嵌,等寫完會 link 到這里的后記里)