这是_.bind
的代码,取自Underscore library。我不了解采用空函数,更改原型等的业务。
var ctor = function(){};
_.bind = function bind(func, context) {
var bound, args;
if (func.bind === nativeBind && nativeBind) return nativeBind.apply(func, slice.call(arguments, 1));
if (!_.isFunction(func)) throw new TypeError;
args = slice.call(arguments, 2);
return bound = function() {
if (!(this instanceof bound)) return func.apply(context, args.concat(slice.call(arguments)));
ctor.prototype = func.prototype;
var self = new ctor;
var result = func.apply(self, args.concat(slice.call(arguments)));
if (Object(result) === result) return result;
return self;
};
};
答案 0 :(得分:8)
它基本上就是这样,如果你调用new bound()
,你就可以绑定new
调用的参数。 E.g:
var func = function(a, b) {
this.a = a;
this.b = b;
};
// context does not matter, use e.g. `null`
var bound = _.bind(func, null, 1);
new bound(2); // a = 1, b = 2
我试着解释一下代码。
var ctor = function(){};
_.bind = function bind(func, context) {
var bound, args;
// use native .bind if available
if (func.bind === nativeBind && nativeBind) return nativeBind.apply(func, slice.call(arguments, 1));
// abort if not called with a function
if (!_.isFunction(func)) throw new TypeError;
// you can also bind arguments, which come after the function and context (so .slice(2))
args = slice.call(arguments, 2);
// return the bound function
return bound = function() {
// if you simply do bound(), then `this` is the global object.
// This means the original function should be called with the
// bound `this` value and arguments. Arguments you pass to the
// bound function are concatenated to the bound arguments.
if (!(this instanceof bound)) return func.apply(context, args.concat(slice.call(arguments)));
// otherwise, you're calling like `new bound()`, because `this instanceof bound`.
// In that case, `this` should not be passed, but only the arguments. So, you
// create a function of which the prototype is the original function's prototype,
// and create an instance of it (to mimic `new func`).
ctor.prototype = func.prototype;
var self = new ctor; // won't execute anything since ctor's body is empty.
// Just creates an instance
// then, you call the original function with the `this` value of the instance,
// with bound arguments and new arguments concatenated. This way, the constructor
// (func) is executed on the instance.
var result = func.apply(self, args.concat(slice.call(arguments)));
// finally, return the result if it's an object (the specs say `new xxx` should
// return an object), otherwise return the instance (like you would with `new func`)
if (Object(result) === result) return result;
return self;
};
};