令人惊讶的是,事实证明这不是问题。如果函数绑定到上下文,则可以使用apply 安全地调用它,而无需更改上下文。
apply 的第一个参数可以设置为任何值 - undefined、null、window、另一个对象。如果函数被绑定,则没有任何作用。
例子:
var o = { id: "foo" },
args = [ "bar", "baz" ],
f = function () {
var args = Array.prototype.slice.call( arguments ).join( ", ");
return "Called in the context of " + this.id + " with args " + args;
},
// Binding f to o with ES5 bind
boundNative = f.bind( o ),
// Binding f to o with a closure
boundWithClosure = ( function ( context ) {
return function () {
return f.apply( context, arguments );
}
} )( o );
// Does boundNative.apply( whatever, args ) change the context?
console.log( boundNative.apply( undefined, args ) );
console.log( boundNative.apply( null, args ) );
console.log( boundNative.apply( window, args ) );
console.log( boundNative.apply( { id: "quux" }, args ) );
// Same test with the closure
console.log( boundWithClosure.apply( undefined, args ) );
console.log( boundWithClosure.apply( null, args ) );
console.log( boundWithClosure.apply( window, args ) );
console.log( boundWithClosure.apply( { id: "quux" }, args ) );
所有调用都返回“在带有 args bar、baz 的 foo 上下文中调用”,所以没有问题。
我不得不承认,这个结果一开始让我很吃惊。毕竟,apply 强制执行上下文 - 为什么会被忽略?但实际上它完全有道理。
是的,原始函数(f)引用this,用apply调用它会改变它的值。但是我们没有调用原始函数。
绑定的函数是一个完全独立的实体,它不再引用this。对于 ES5 bind 来说,这不是很明显,但是闭包结构把它暴露了。 this 关键字不会出现在 IIFE 返回的函数中的任何位置。调用它,apply 没有什么可以改变的。