我在stackoverflow上检查了很多类似的问题,例如call.call 1,call.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()之间的工作方式有何不同
有人可以帮忙吗?谢谢!
答案 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.call
和my.call
)相同的功能,依此类推,您就可以添加尽可能多的.call
属性访问你想要的,它不会改变任何东西。
截至你的第二个问题:
var $ = Function.prototype.call
$(my, this, 'Hello5')
不起作用,因为函数调用的上下文是在调用期间动态设置的(除非它与.bind()
绑定或是ES2015箭头函数)。
因此,当您将其作为$
调用时,未明确设置上下文(因为它是变量,而不是对象),因此默认情况下它设置为undefined
或全局对象(取决于您运行代码的方式)。
答案 1 :(得分:0)
每个对象都链接到一个原型对象。在尝试检索对象上不存在的属性时,将查找其原型对象。 Read more
this
是JavaScript函数中可用的特殊变量。它的值取决于你如何调用函数,而不是你如何定义函数(有一些例外)。 Read more
如您所见,call
在Function.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()