Skip to content

Instantly share code, notes, and snippets.

@jrburke
Created August 17, 2011 20:58
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jrburke/1152608 to your computer and use it in GitHub Desktop.
Save jrburke/1152608 to your computer and use it in GitHub Desktop.
(null,eval)('')
//Came across this in the es-discuss list, on the "clean scope" thread:
https://mail.mozilla.org/pipermail/es-discuss/2011-August/thread.html#16294
//I do not understand what the "null," part buys.
//Has to do something with scope(?), but at least in Firebug,
//I can see foo inside the string being evaled.
var foo = 'foo';
(null,eval)('(function(){console.log(foo);}())');
//Prints "foo" in Firebug console.
@samsonjs
Copy link

Try it wrapped in a function, Firebug uses eval itself.

(function() {
  var foo = 'foo';
  (null,eval)('(function(){console.log(foo);}())');
}())

vs

(function() {
  var foo = 'foo';
  eval('(function(){console.log(foo);}())');
}())

null itself is not relevant, the important thing is that the comma expression results in the eval function but not by a directly named reference.

@alunny
Copy link

alunny commented Aug 17, 2011

(null,eval) makes an indirect eval call, which executes the code in the global scope (rather than the scope of the caller).

@kangax has an excellent article about global/indirect eval here:
http://perfectionkills.com/global-eval-what-are-the-options/#indirect_eval_call_theory

@mikaelgramont
Copy link

Try this:
(null, console.log)('blah');

It seems to do the same thing as these:
(console.warn, console.log)('blah');
(console.log)('blah');
console.log('blah');

So I guess it has nothing to do with eval, maybe the goal was to go around a particular browser quirk?

@mikaelgramont
Copy link

Ah, I should have waited a bit for someone to post the correct answer :p

@samsonjs
Copy link

Also, if you define foo in the global scope and then use an indirect eval foo will still be in scope. That's another reason why you want to wrap those 2 statements in a function.

@jrburke
Copy link
Author

jrburke commented Aug 17, 2011

Thanks all for the answers.

@dherman
Copy link

dherman commented Aug 17, 2011

It's absolutely about eval, not about browser quirks. When you write

eval(/* blah */)

or even

(((((eval)))))(/* blah */)

it's specified in the standard to be a "direct eval" which has access to the local scope. But when you write

(null, eval)(/* blah */)

it's an "indirect eval," which is evaluated in the global scope.

The null isn't particularly special; it would also work to replace the null with 42 or /someregex/ or "this is a srsly weird language feature".

Dave

@CrabDude
Copy link

@netroy
Copy link

netroy commented Aug 18, 2011

ah... i learn something new everyday ... :)

so its about whether the reference is named or not
eval() would execute in local scope, but any other reference to eval would execute in global scope

the following execute in a global scope

  • (null, eval)('')
  • (x=eval)('')
  • var x=eval; x('')
  • var eval=window.eval; eval('')
  • window.eval('')
  • eval.call(window,'')

edit: and i found this http://perfectionkills.com/global-eval-what-are-the-options/#indirect_eval_call_examples :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment