我需要您的帮助才能更好地理解以下行为。
在下面的代码段中,我们可以看到fooBar
输出foo
为this
,然后按预期输出returns bar 1, 2, 3
-意味着bar
被{{ 1}}作为上下文。
foo
现在我们改为使用const arguments = [1,2,3];
function bar(...args) {
console.log('bar this ->', this);
return 'bar ' + args;
}
function foo(...args) {
console.log('foo this ->', this);
return 'foo ' + args;
}
const fooBar = bar.bind(foo, null)(arguments);
console.log(fooBar); // <--- no surprises!
。
const bar = Math.max.apply;
在这种情况下,调用const arguments = [1,2,3];
const bar = Math.max.apply;
function foo(...args) {
console.log('foo this ->', this);
return 'foo ' + args;
}
const fooBar = bar.bind(foo, null)(arguments);
console.log(fooBar); // <--- surprise!
而不是foo
。为什么?在这种情况下,bar
到底在做什么?我假设应该再次以bind()
作为上下文来调用bar
。在这种情况下,上下文为foo
。
我一直认为 someFunction.apply(someContext,args) 表现为 someFunction.bind(someContext,null)(args),但是在第二个示例中, someFunction.bind(someContext,null)(args) 表现为 someContext(args)。
答案 0 :(得分:1)
bind
正在创建一个新函数,该函数调用其this
值(bar
,它是apply
的副本),并将您作为新值传递给它的值this
值。
由于bar
是apply
的副本:
bar.bind(foo)()
与foo.bar()
和foo.apply()
相同。
答案 1 :(得分:1)
这是由于apply
的特定目的:调用给定函数。请记住,bar
是通用的Function.prototype.apply
函数。
bind
本质上是使用上下文(this
值)和(可选)预设的参数创建原始函数的副本。 bind
的polyfill将在内部使用apply
。
所以fooBar = bar.bind(foo, null)
与
function fooBar(...args) {
return Function.prototype.apply.apply(foo, [null, args]);
}
apply
的双重使用显然令人困惑!
让我们逐步完成bar.bind(foo, null)(arguments)
的操作:
Function.prototype.apply.bind(foo, null)(arguments)
可以减少为
Function.prototype.apply.apply(foo, [null, arguments])
在此特定情况下与
相同foo(null, ...arguments);
之所以如此令人困惑,是因为您正在对apply
函数进行复杂的调用,该函数是为函数的复杂调用而设计的!
答案 2 :(得分:1)
让我们进行模仿本地myApply
的“临时” Function#apply
,以更好地了解Function#apply
的工作方式。
Function.prototype.myApply = function(args) {
// some checks should be here to see if 'this' is a function and if 'args' is an array-like
this(...args);
}
它需要一个包含参数的数组(或类似数组的对象),并调用this
(适用于myApply
的任何对象),该数组应该是一个函数,其中传递了args
中的每一项作为独立参数。
简单示例:
现在,当您这样做时:
alert.myApply(["hello, there"]);
alert
作为this
传递给myApply
(不言而喻),而["hello, there"]
作为args
传递,一切正常。
令人困惑的示例:
现在,当您使用this
,myApply
甚至bind
来显式设置call
的{{1}}的{{1}}时,
apply
var myApply = alert.myApply;
var newFunction = myApply.bind(foo);
成为新函数(等效于绑定到newFunciton
的{{1}}的函数)。调用myApply
就像调用foo
并将newFunction
设置为myApply
的{{1}}一样。调用this
时,将调用其foo
值(在这种情况下为myApply
)。
附加说明:如您所见,this
不会混淆其foo
(它是一个函数)的上下文,因此该函数将被调用不论调用myApply
之前的上下文如何,在此特定示例中,它都是全局对象this
(myApply
的{{1}}是window
)。>