我从MDN文档中读到.apply和.call的第一个参数是“this”对象,但是
var stringToEval = "console.log(this)";
eval.call(null, stringToEval);
eval.apply(null, [stringToEval]);
在上面的代码中,两行最终都记录了Window对象(在浏览器中)。它不应该记录null,这是我作为两个方法中的第一个参数传递的内容吗?
答案 0 :(得分:2)
来自MDN:
为乐趣召唤提供的价值。请注意,这可能不是方法看到的实际值:如果方法是非严格模式代码中的函数,则null和undefined将替换为全局对象,并且原始值将被装箱。
全局对象是窗口。
编辑,因为无论是传入null,未定义还是带有eval的对象都无关紧要。在eval
内,this
将在eval调用之前与this
相同。
根据ECMA-262 5.1的第15.1.2.1节,eval接受一个字符串并将其解析为ECMAscript。如果它是有效的ECMAscript,那么它将在调用它的上下文中运行它。因此,在您的情况下,您可以将对eval的调用视为在运行时将它们替换为console.log(this)
。通过该替换,您最终得到了该程序:
var stringToEval = "console.log(this)";
console.log(this);
console.log(this);
这清楚了为什么它输出DOMWindow
对象两次。你可以像这样绕过它:
var stringToEval = "console.log(this)";
(function(str){ eval(str); }).call({not: "empty"}, stringToEval);
(function(str){ eval(str); }).apply({not: "empty"}, [stringToEval]);
因为当eval用console.log(this)
替换它时,它将位于匿名函数的上下文中,其中this
将引用传入的对象。
答案 1 :(得分:0)
您通过明确将eval
设置为this
来致电null
,这与this
对象内部的内容无关
代码,没有任何地方说eval
评估代码,this
设置为与this
调用的eval
相同的eval
。实际上,这样做是调用function test() {
console.log(this);
}
test.call({});
test.apply({});
indirectly并导致eval代码在现代浏览器的全局上下文中运行。
因此,您希望使用正常功能进行测试:
{{1}}