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;
)。非常感谢你的投入!我现在在路上,回家后会仔细看看。听起来是正确的答案!