Reputation: 9854
I read from the MDN docs that the first argument of .apply and .call is the "this" object, but
var stringToEval = "console.log(this)";
eval.call(null, stringToEval);
eval.apply(null, [stringToEval]);
in the code above both lines end up logging the Window object (in a browser). Shouldn't it log null, that is what I passed as the first argument in both methods ?
Upvotes: 3
Views: 1709
Reputation: 141839
From MDN:
The value of this provided for the call to fun. Note that this may not be the actual value seen by the method: if the method is a function in non-strict mode code, null and undefined will be replaced with the global object, and primitive values will be boxed.
The global object is window.
Edit since it doesn't matter whether you pass in null, undefined, or an object with eval. Inside eval
, this
will be the same as this
right before the eval call.
As per section 15.1.2.1 of ECMA-262 5.1, eval takes in a string and parses it as ECMAscript. If it is valid ECMAscript then it runs it, in the context that it was called from. So in your case you can think of the calls to eval as if they replace themselves with console.log(this)
at runtime. With that replacement you end up with the program:
var stringToEval = "console.log(this)";
console.log(this);
console.log(this);
Which makes it clear why it outputs the DOMWindow
object twice. You can get around it like this:
var stringToEval = "console.log(this)";
(function(str){ eval(str); }).call({not: "empty"}, stringToEval);
(function(str){ eval(str); }).apply({not: "empty"}, [stringToEval]);
Since when eval replaces itself with console.log(this)
it will be in the context of that anonymous function in which this
will refer to the object passed in.
Upvotes: 2
Reputation: 140220
You call eval
with explicitly set this
to null
, this has nothing to do with what the this
object will be inside the evaled
code, nowhere is it said that eval
evaluates the code with this
set to the same this
that you called eval
with. In fact, doing so is calling eval
indirectly and results in the eval code being run in global context for modern browsers.
Therefore, you want to test with normal function:
function test() {
console.log(this);
}
test.call({});
test.apply({});
Upvotes: 0