bind函數(shù)
參考:JavaScript深入之bind的模擬實(shí)現(xiàn)
bind(function, object, *arguments):綁定函數(shù) function 到對(duì)象 object 上, 也就是無論何時(shí)調(diào)用函數(shù), 函數(shù)里的 this 都指向這個(gè) object。
我們先看上面的參考博文的實(shí)現(xiàn),其中有幾個(gè)要點(diǎn):
-
bind的基本實(shí)現(xiàn)(用閉包保存bind傳進(jìn)來的上下文) -
bind是可以傳部分或者全部參數(shù)的 -
bind后的函數(shù)是依舊可以當(dāng)做構(gòu)造函數(shù)來使用并且忽略bind提供的this的
再結(jié)合《你不知道的JavaScript(上)》里的bind,我們可以得到這樣一個(gè)bind
Function.prototype.myBind = function (context) {
context = Object(context) || window;
var self = this;
var args = [].slice.call(arguments, 1);
var constructor = function () {
args = args.concat([].slice.call(arguments));
if (this instanceof self) {
// 說明正在使用new
return self.apply(this, args);
} else {
// 普通的bind使用方法
return self.apply(context, args);
}
}
constructor.prototype = Object.create(self.prototype);
return constructor;
}
然后我們來看看underscore中的_.bind
_.bind = function (func, context) {
// nativeBind
if (nativeBind && func.bind === nativeBind) return nativeBind.apply(func, slice.call(arguments, 1));
// 上下文校驗(yàn)
if (!_.isFunction(func)) throw new TypeError('Bind must be called on a function');
// 保存部分參數(shù)
var args = slice.call(arguments, 2);
var bound = function () {
return executeBound(func, bound, context, this, args.concat(slice.call(arguments)));
};
return bound;
};
我們也看到bind函數(shù)實(shí)現(xiàn)的核心是executeBound函數(shù),它有5個(gè)參數(shù)
-
func:bind的目標(biāo)函數(shù) -
bound:bind的返回函數(shù) -
context:綁定上下文 -
this:執(zhí)行上下文 -
args:執(zhí)行參數(shù)
明白了參數(shù)的意義,我們?cè)賮砜?code>executeBound的實(shí)現(xiàn)
var executeBound = function (sourceFunc, boundFunc, context, callingContext, args) {
if (!(callingContext instanceof boundFunc)) return sourceFunc.apply(context, args);
var self = baseCreate(sourceFunc.prototype);
var result = sourceFunc.apply(self, args);
if (_.isObject(result)) return result;
return self;
};
其實(shí)思路就跟之前的bind函數(shù)是一樣的了。
- 判斷執(zhí)行上下文是否是
new賦值的新this - 如果不是,當(dāng)做普通的
bind返回函數(shù) - 如果是,則需要當(dāng)做構(gòu)造函數(shù)使用,就需要添加
prototype和檢驗(yàn)返回結(jié)果 -
baseCreate添加原型,result檢驗(yàn)構(gòu)造函數(shù)是否有返回值; - 如果這個(gè)返回值是對(duì)象,就返回這個(gè)對(duì)象;否則返回
構(gòu)造函數(shù)執(zhí)行的結(jié)果。
于是發(fā)現(xiàn),Underscore源碼實(shí)現(xiàn)的bind函數(shù),跟我們之前實(shí)現(xiàn)的是一樣的。