我从 MDN 文档中了解到,.apply 和 .call 的第一个参数是“this”对象,但是
var stringToEval = "console.log(this)";
eval.call(null, stringToEval);
eval.apply(null, [stringToEval]);
在上面的代码中,这两行最终都会记录浏览器中的Window对象。难道它不应该记录null吗?因为我在两种方法的第一个参数中传递了null。
我从 MDN 文档中了解到,.apply 和 .call 的第一个参数是“this”对象,但是
var stringToEval = "console.log(this)";
eval.call(null, stringToEval);
eval.apply(null, [stringToEval]);
提供给fun调用的this值。请注意,方法实际上看到的可能不是这个值:如果该方法是非严格模式代码中的函数,则null和undefined将被替换为全局对象,并且原始值将被封装。
全局对象是window。
编辑,因为传入null、undefined或带有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]);
console.log(this)
替换自身之后,它将在匿名函数的上下文中,其中 this
将指向传递进来的对象。
当你使用eval
并将this
显式设置为null
时,这与在evaled代码内部的this
对象无关。没有任何地方说eval
会使用与调用eval
相同的this
进行评估。事实上,这样做是间接调用eval
,对于现代浏览器,结果是在全局上下文中运行eval代码。
因此,您需要使用普通函数进行测试:
function test() {
console.log(this);
}
test.call({});
test.apply({});
this
总是window
。它与.call
或.apply
没有任何关系。 - Esailija