首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Function.call、Function.prototype.call、Function.prototype.call.call和Function.prototype.call.call.call的区别

Function.call、Function.prototype.call、Function.prototype.call.call和Function.prototype.call.call.call的区别
EN

Stack Overflow用户
提问于 2017-04-15 16:57:36
回答 3查看 672关注 0票数 1

我已经在stackoverflow上检查了很多类似的问题,比如call.call 1call.call 2,但我是一个新手,我不能在任何地方发表评论。我希望我能找到一个关于JavaScript解释器如何执行这些函数的全面而透彻的解释,并在这里打开一个新的问题。

下面是一些示例:

代码语言:javascript
复制
function my(p) { console.log(p) }
Function.prototype.call.call(my, this, "Hello"); // output 'Hello'

上面的例子是Function.prototype.call的标准用法,更容易理解。我的理解是:' my‘作为一个函数对象执行它继承的方法'Function.prototype.call’。my.(Function.prototype.call) => my.call(this,'Hello')

代码语言:javascript
复制
Function.call.call(my, this, "Hello") // output 'Hello'

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

代码语言:javascript
复制
Function.prototype.call(my, this, 'Hello2') // output nothing
Function.call(my, 'Hello2') // output nothing

我无法解释为什么这条语句没有抛出错误?事实上,我不知道Function.prototype.call作为一种方法是如何工作的。

代码语言:javascript
复制
Function.prototype.call.call.call(my, this, "Hello3"); // output 'Hello3'

我无法解释JavaScript解释器如何解释上述语句?从右到左解释“call”?那么我的.(Function.prototype.call.call)是什么意思?

代码语言:javascript
复制
Function.prototype.call.call.call.call(my, this, "Hello4"); // output 'Hello4'

为什么我可以在这里输入任意数量的'.call‘,而输出却是一样的?不是每个调用都消耗一个参数作为'this‘对象吗,这应该意味着只有三个参数是不够的?与上面的问题类似的问题

然后是更多的例子:

代码语言:javascript
复制
var $ = Function.prototype.call
$(my, this, 'Hello5') // Exception: TypeError: Function.prototype.call called on incompatible Proxy

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

代码语言:javascript
复制
var v = Function.prototype.call.call 
v(my, this, 'Hello6') // Exception: TypeError: Function.prototype.call called on incompatible Proxy

这是否意味着,当使用变量v时,JavaScript解释器试图孤立地解释v,而没有看到后面有参数?然后解释器认为'this‘是全局变量'window'?我不知道v()和Function.prototype.call.call()的解释器有什么不同。

有人能帮帮忙吗?谢谢!

EN

回答 3

Stack Overflow用户

发布于 2017-04-15 17:25:59

Function.prototype.call.call(my, this, "Hello");的意思是:

使用my作为经过call编辑的函数的this参数(函数上下文)。在本例中,调用了Function.prototype.call

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

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

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

代码语言:javascript
复制
Function.prototype.call.call(my, 123, 'Hello2') // outputs "Hello2"

一旦Function.prototype.call.call引用了与Function.prototype.call.call.call (以及Function.callmy.call)相同的函数,您就可以添加任意数量的.call属性访问,并且它不会更改任何内容。

在您的第二个问题中:

代码语言:javascript
复制
var $ = Function.prototype.call
$(my, this, 'Hello5')

不起作用,因为函数调用的上下文是在调用过程中动态设置的(除非它绑定了.bind()或者是一个ES2015箭头函数)。

因此,当您将其作为$调用时,上下文没有显式设置(因为它是一个变量,而不是一个对象),所以在默认情况下,它被设置为undefined或全局对象(取决于您运行代码的方式)。

票数 1
EN

Stack Overflow用户

发布于 2017-04-18 22:01:05

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

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

正如您所看到的,call是在Function.prototype上定义的,这意味着所有函数对象都可以访问它。它是一个特殊的函数,因为它允许您在调用函数时显式设置this的值。

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

代码语言:javascript
复制
function f(){
    const args = Array.prototype.slice.call( arguments );
    // `args` is now a real array with all the privileged functions.
}

回到你的例子,

代码语言:javascript
复制
function my(p) { console.log(p) }
Function.prototype.call.call(my, this, "Hello"); // output 'Hello'

在这里,您将在Function.prototype.call上调用call

它等同于

代码语言:javascript
复制
function my(p) { console.log(p) }
my.call(this, "Hello"); // output 'Hello'

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

代码语言:javascript
复制
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,在window·中为window)。

代码语言:javascript
复制
var v = Function.prototype.call.call 
v(my, this, 'Hello6') // Exception: TypeError: Function.prototype.call called on incompatible Proxy

这就是为什么你会收到这个错误,正如call所期望的那样,this不是一个函数。当您从对象调用函数时,this将引用该对象,这就是当您在某些函数上调用call时发生的情况(函数也是对象)。

票数 0
EN

Stack Overflow用户

发布于 2020-01-01 16:46:54

我纠结于这个问题,因为我在精神上很难从' this‘这个参数中跳出来,这个参数然后被视为调用方法所在的伪对象。我总结了我的理解(在Nodejs中):

代码语言:javascript
复制
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?

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/43424141

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档