我从 MDN 文档中读到 .apply 和 .call 的第一个参数是“this”对象,但是
var stringToEval = "console.log(this)";
eval.call(null, stringToEval);
eval.apply(null, [stringToEval]);
在上面的代码中,两行最终都记录了 Window 对象(在浏览器中)。它不应该记录 null,这就是我在两种方法中作为第一个参数传递的内容吗?
我从 MDN 文档中读到 .apply 和 .call 的第一个参数是“this”对象,但是
var stringToEval = "console.log(this)";
eval.call(null, stringToEval);
eval.apply(null, [stringToEval]);
在上面的代码中,两行最终都记录了 Window 对象(在浏览器中)。它不应该记录 null,这就是我在两种方法中作为第一个参数传递的内容吗?
来自MDN:
这为有趣的呼吁提供了价值。请注意,这可能不是方法看到的实际值:如果方法是非严格模式代码中的函数,null 和 undefined 将被替换为全局对象,原始值将被装箱。
全局对象是窗口。
编辑,因为无论您传入 null、未定义还是带有 eval 的对象都没有关系。内部eval
,this
将与this
eval 调用之前相同。
根据 ECMA-262 5.1 的第 15.1.2.1 节,eval 接收一个字符串并将其解析为 ECMAscript。如果它是有效的 ECMAscript,那么它会在调用它的上下文中运行它。console.log(this)
因此,在您的情况下,您可以将对 eval 的调用视为它们在运行时替换自己。有了这个替换,你最终得到了这个程序:
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
将引用传入的对象。
您eval
使用显式设置this
为调用null
,这与this
对象将在评估代码中的内容无关,没有任何地方说使用设置eval
评估代码与您调用的代码this
相同。事实上,这样做是间接调用,并导致 eval 代码在现代浏览器的全局上下文中运行。this
eval
eval
因此,您要使用正常功能进行测试:
function test() {
console.log(this);
}
test.call({});
test.apply({});