Javascript 链接.apply()和.bind()异常行为
我需要你的帮助来更好地理解以下行为 在下面的代码片段中,我们可以看到Javascript 链接.apply()和.bind()异常行为,javascript,ecmascript-6,Javascript,Ecmascript 6,我需要你的帮助来更好地理解以下行为 在下面的代码片段中,我们可以看到fooBar将foo输出为this,然后按预期返回条1、2、3——这意味着bar是以foo作为上下文调用的 const参数=[1,2,3]; 功能栏(…参数){ log('bar this->',this); 返回'bar'+参数; } 函数foo(…args){ log('foo this->',this); 返回'foo'+参数; } const fooBar=bar.bind(foo,null)(参数); console
fooBar
将foo
输出为this
,然后按预期返回条1、2、3
——这意味着bar
是以foo
作为上下文调用的
const参数=[1,2,3];
功能栏(…参数){
log('bar this->',this);
返回'bar'+参数;
}
函数foo(…args){
log('foo this->',this);
返回'foo'+参数;
}
const fooBar=bar.bind(foo,null)(参数);
console.log(fooBar);// bind
正在创建一个新函数,该函数调用其this
值(bar
,它是apply
的副本),并将传递给它的值作为新的this
值
由于bar
是apply
的副本:
bar.bind(foo)(
与foo.bar()
与foo.apply()
这是因为apply
的特定目的:调用给定函数。请记住,bar
是通用的函数.prototype.apply
函数
bind
基本上创建了原始函数的副本,并预设了上下文(此
值)和(可选)参数。bind
的polyfill将在内部使用apply
因此fooBar=bar.bind(foo,null)
与
function fooBar(...args) {
return Function.prototype.apply.apply(foo, [null, args]);
}
foo(null, ...arguments);
双重使用apply
显然令人困惑
让我们逐步了解一下bar.bind(foo,null)(参数)
的作用:
Function.prototype.apply.bind(foo, null)(arguments)
这可以归结为
Function.prototype.apply.apply(foo, [null, arguments])
在这个特定的实例中,与
function fooBar(...args) {
return Function.prototype.apply.apply(foo, [null, args]);
}
foo(null, ...arguments);
之所以如此令人困惑,是因为您正在对apply
函数进行复杂调用,该函数是为复杂的函数调用而设计的 让我们自己做一个“临时的”myApply
,模仿本地的函数#apply
,更好地理解函数#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"]);
警报
作为此
传递给myApply
(不言自明),而[“你好”]
作为参数传递,一切正常
令人困惑的例子:
现在,当您使用bind
显式设置this
的myApply
时,调用
甚至apply
如下所示:
var myApply = alert.myApply;
var newFunction = myApply.bind(foo);
newfunction
成为一个新函数(相当于绑定到foo
的myApply
函数)。调用newFunction
就像调用myApply
,其this
设置为foo
。调用myApply
时,将调用其this
值(在本例中为foo
)
附加说明:正如您所看到的myApply
不会混淆其this
(这是一个函数)的上下文,因此该函数将在调用myApply
之前的任何上下文中被调用,在这个特定示例中,它是全局对象窗口
(foo
的这是窗口
).为什么选择Math.max.apply
呢?它根本没有任何效果,它与执行const bar=Function.prototype.apply;
或const bar=alert.apply
或任何其他函数相同:您只是引用了类函数的方法apply
。没有特别的原因除此之外的选择:甚至使我自己困惑more@lustoykov也许你的意思是const bar=Function.prototype.apply.bind(Math.max)
谢谢@Bergi,这并不是让我困惑的原因。我认为@lonesomeday给出的答案最接近我的理解,但有些东西没有加起来,因为Function.prototype.apply.apply(foo,null)(参数)
不是正确的syntax@lustoykov还要注意,.bind(foo,null)(arg)
无论如何都是不正确的。它应该是.bind(foo)(arg)
或.bind(null)(arg)
嘿,谢谢你的输入!你的最后一句话是正确的,但我只担心bar是Function.prototype.apply的情况,这里有一个反例:。这就是我试图理解的-为什么它在这种情况下表现不同。为什么它在应用时表现不同?嗯……什么是bind()在幕后做什么?如果我能在某处找到实现的话!这些陈述是正确的,这也是我的结论,但我不明白为什么它在apply
apply
中没有表现出不同的行为,它只是在给定这个值的情况下做它所做的事情。@lustoykov实际上是你的jsbin示例I这并不是昆汀想说的。它应该是一样的bar
,应该是apply
(即const bar=Function.prototpe.apply;
)。非常感谢你的投入!我现在在路上,回家后会仔细看看。听起来是正确的答案!