Function.call,Function.prototype.call,Function.prototype.call.call和Function.prototype.call.call.call

时间:2017-04-15 08:57:36

标签: javascript functional-programming prototype call

我在stackoverflow上检查了很多类似的问题,例如call.call 1call.call 2,但我是新手,我无法在任何地方发表评论。我希望我能找到一个全面而全面的解释,说明JavaScript解释器如何执行这些函数,并在此处打开一个新问题。

以下是一些例子:

function my(p) { console.log(p) }
Function.prototype.call.call(my, this, "Hello"); // output 'Hello'

上面的示例是Function.prototype.call的标准用法,它更容易理解。我的理解是:'我的'作为一个函数对象执行其继承的方法' Function.prototype.call'即。我的。(Function.prototype.call)=> my.call(这,'你好')

Function.call.call(my, this, "Hello") // output 'Hello'

与上面的例子相比,我很困惑。我不知道JavaScript解释器在这里是如何工作的。 '我'将Function.call和Function.prototype.call视为相同的方法?

Function.prototype.call(my, this, 'Hello2') // output nothing
Function.call(my, 'Hello2') // output nothing

我无法解释为什么这句话不会引发错误?实际上,我不知道Function.prototype.call是如何工作的。

Function.prototype.call.call.call(my, this, "Hello3"); // output 'Hello3'

我无法解释JavaScript解释器如何解释上述语句?口译'电话'从右到左?那么我的。(Function.prototype.call.call)是什么意思?

Function.prototype.call.call.call.call(my, this, "Hello4"); // output 'Hello4'

为什么我可以输入任意数量的' .call'在这里,输出是一样的吗?每个电话都不会消费一个论点,因为这个'对象,这应该意味着只有三个参数是不够的?与上面的一个类似的问题

然后是更多例子:

var $ = Function.prototype.call
$(my, this, 'Hello5') // Exception: TypeError: Function.prototype.call called on incompatible Proxy

为什么它不输出任何内容,就像上面的例子一样?

var v = Function.prototype.call.call 
v(my, this, 'Hello6') // Exception: TypeError: Function.prototype.call called on incompatible Proxy

这是否意味着,当使用变量v时,JavaScript解释器会尝试孤立地解释v,而不会看到后面有参数?然后口译员会认为这个'这个'是全球变量' window'?我不知道解释器在v()和Function.prototype.call.call()之间的工作方式有何不同

有人可以帮忙吗?谢谢!

3 个答案:

答案 0 :(得分:1)

Function.prototype.call.call(my, this, "Hello");表示:

my ed函数使用this作为call参数(函数上下文)。在这种情况下,Function.prototype.call被调用。

因此,Function.prototype.call将以my作为其上下文进行调用。这基本上意味着 - 它将是被调用的函数。

将使用以下参数调用它:(this, "Hello"),其中this是要调用的函数内的上下文(在本例中为my ),唯一要传递的参数是"Hello" string。

只要您的my函数没有以任何方式使用this上下文,您就可以传递任何内容:

Function.prototype.call.call(my, 123, 'Hello2') // outputs "Hello2"

只要Function.prototype.call.call引用与Function.prototype.call.call.call(以及Function.callmy.call)相同的功能,依此类推,您就可以添加尽可能多的.call属性访问你想要的,它不会改变任何东西。

截至你的第二个问题:

var $ = Function.prototype.call
$(my, this, 'Hello5')

不起作用,因为函数调用的上下文是在调用期间动态设置的(除非它与.bind()绑定或是ES2015箭头函数)。

因此,当您将其作为$调用时,未明确设置上下文(因为它是变量,而不是对象),因此默认情况下它设置为undefined或全局对象(取决于您运行代码的方式)。

答案 1 :(得分:0)

每个对象都链接到一个原型对象。在尝试检索对象上不存在的属性时,将查找其原型对象。 Read more

this是JavaScript函数中可用的特殊变量。它的值取决于你如何调用函数,而不是你如何定义函数(有一些例外)。 Read more

如您所见,callFunction.prototype上定义,这意味着所有功能对象都可以访问它。它是一个特殊的函数,它允许您在调用函数时显式设置this的值。

一种常见用法是在类似数组的对象上调用数组函数,这些对象不从Array.prototype继承:

function f(){
    const args = Array.prototype.slice.call( arguments );
    // `args` is now a real array with all the privileged functions.
}

回到你的例子,

function my(p) { console.log(p) }
Function.prototype.call.call(my, this, "Hello"); // output 'Hello'

您要在call上致电Function.prototype.call

相当于

function my(p) { console.log(p) }
my.call(this, "Hello"); // output 'Hello'

由于在call上定义Function.prototype,并且它本身就是一个函数,当您两次调用call时,您正在检索相同的函数。这就是为什么你可以无限期地链接它们。

function my(p) { console.log(p) }
const call1 = Function.prototype.call;
const call2 = Function.prototype.call.call;    // Same as `call1.call`.
const call3 = my.call;

console.log( call1 === call2 );
console.log( call1 === call3 );

现在问题的第二部分。 this如何在函数内部工作。 Read more

要记住的是,值是根据您调用函数的方式动态确定的,而不是您如何定义它(除了一些例外)。

执行此操作时,call函数的this值将是当前范围内的值(在全局范围内,在严格模式下为undefined且{{1松散的。)。

window

这就是你收到错误的原因,var v = Function.prototype.call.call v(my, this, 'Hello6') // Exception: TypeError: Function.prototype.call called on incompatible Proxy 不是一个函数,正如this所期望的那样。当您从对象调用函数时,call将引用 那个对象,就是当你在某个函数上调用this时所发生的事情(函数也是对象)。

答案 2 :(得分:0)

我在这个问题上苦苦挣扎,因为在精神上我很难摆脱“ this”这个参数的跳跃,然后将其视为一种伪对象,从该伪对象中调用call方法。我总结了我的理解(在Nodejs中):

function f(a) {console.log(a);}

f.call(global, 1);
//function reference to be called = f
//context to call it from = global
//parameters used when invoking = 1
//equivalent call => global.f(1)

Function.prototype.call.call(f, global, 1);
//function reference to be called = Function.prototype.call
//context to call it from = f
//parameters used when invoking = global, 1
//equivalent call => f.call(global, 1)

使用的参考文献:

A shorthand for Function.prototype.call.call?

Javascript Function.prototype.call()

Can't use Function.prototype.call directly

a is a function, then what `a.call.call` really do?