3

我从 MDN 文档中读到 .apply 和 .call 的第一个参数是“this”对象,但是

var stringToEval = "console.log(this)";
eval.call(null, stringToEval);
eval.apply(null, [stringToEval]);

在上面的代码中,两行最终都记录了 Window 对象(在浏览器中)。它不应该记录 null,这就是我在两种方法中作为第一个参数传递的内容吗?

4

2 回答 2

2

来自MDN

这为有趣的呼吁提供了价值。请注意,这可能不是方法看到的实际值:如果方法是非严格模式代码中的函数,null 和 undefined 将被替换为全局对象,原始值将被装箱。

全局对象是窗口。

编辑,因为无论您传入 null、未定义还是带有 eval 的对象都没有关系。内部eval,this将与thiseval 调用之前相同。

根据 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将引用传入的对象。

看到这个 JSFiddle

于 2012-06-07T05:28:01.353 回答
0

eval使用显式设置this为调用null,这与this对象将在评估代码中的内容无关,没有任何地方说使用设置eval评估代码与您调用的代码this相同。事实上,这样做是间接调用,并导致 eval 代码在现代浏览器的全局上下文中运行。thisevaleval

因此,您要使用正常功能进行测试:

function test() {
    console.log(this);
}

test.call({});
test.apply({});
于 2012-06-07T05:51:25.600 回答