void(document.body.innerText += 'hi')
eval(document.body.innerText +='\nbye')
Function(document.body.innerText += '\n!!!')
void(Function(function foo(){document.body.innerText += '\n>hi2'; return true}).toString())();
eval(Function(function foo(){document.body.innerText += '\nbye2'; return true}).toString())();
Function(Function(function foo(){document.body.innerText += '\n!!!2'; return true}).toString())();
void(document.body.innerText += 'hi')
eval(document.body.innerText +='\nbye')
Function(document.body.innerText += '\n!!!')
void(Function(function foo(){document.body.innerText += '\n>hi2'; return true}).toString())();
eval(Function(function foo(){document.body.innerText += '\nbye2'; return true}).toString())();
Function(Function(function foo(){document.body.innerText += '\n!!!2'; return true}).toString())();
What's the processing model for executing code within these different statements?
void(alert('hi'))
undefined
eval(alert('hi'))
undefined
Function(alert('hi'))
function anonymous() {
undefined
}
eval(Function(function foo(){return true}).toString())();
TypeError: undefined is not a function
void(Function(function foo(){return true}).toString())();
TypeError: string is not a function
Function(Function(function foo(){return true}).toString())();
undefined
Share
Improve this question
edited Jan 28, 2016 at 20:53
Paul Sweatte
asked Apr 27, 2012 at 1:16
Paul SweattePaul Sweatte
24.6k7 gold badges131 silver badges268 bronze badges
3 Answers
Reset to default 5In this article the eval
and Function
constructors are explained:
(…) Global, built-in
eval
function evaluates code in the scope of a caller.The code executed from within function created by
Function
constructor doesn’t really execute in global scope. However, it doesn’t execute in local scope either, which is what probably leads to confusion.Function
constructor creates a function whose scope chain consists of nothing but a global scope (preceded with function’s own Activation Object, of course). Any code contained in a function created viaFunction
constructor evaluates in a scope of that function, not in a global scope. However, it’s almost as if code executes globally, since global object is the very next object in the scope chain.
And according to this page, void
just returns undefined
:
In many languages,
void
is a type that has no values. In JavaScript,void
is an operator that takes an operand and returnsundefined
. This is not useful, and it is very confusing. Avoidvoid
.
Here is a summary of the evaluation differences:
void
evaluates code in the containing function scopeeval
evaluates strings in the containing function scopeFunction
evaluates code in its own scope
and the return differences:
void
always returns undefinedeval
returns the return value of the executed codeFunction
returns an anonymous function
References
- JS101: The Function Constructor
- JSLint Error Explanations: The Function constructor is eval
- How Evil is Eval
- [[Scope]] of functions created via Function constructor
- Evaluating JavaScript code via eval() and new Function()
- Gmail for Mobile HTML5 Series: Reducing Startup Latency - The official Google Code blog
- Faster Loading Through Eval() – SproutCore
- (down)Loading JavaScript as strings | High Performance Web Sites
- Expressions versus statements in JavaScript - Dr. Axel Rauschmayer
- The void operator in JavaScript
It's worth noting that you are pletely misusing these functions.
void
just evaluates some expression and returns undefined.Note it's an operator and not a function, so no need to wrap the operant inside parentheses.
This is only useful to get the value undefined if you worry
undefined
could be shadowed, or if you want to type less characters.Instead of
var undef = void(document.body.innerText += 'hi')
better use
document.body.innerText += 'hi'; var undef = void 0;
And if you don't need to get undefined, don't use
void
at all.eval
is supposed to be called with a string. It evaluates that string as code. The exact behavior depends on whether you call it in strict or sloppy mode, and whether it's a direct or indirect call.If you don't call it with a string, it will just return the argument.
In your case,
eval(document.body.innerText += '\nbye')
will:- Run
document.body.innerText += '\nbye'
, returns the new value, e.g."hello\nbye"
. - Evaluate the resulting text as code. Most probably this will throw.
I'm almost sure
eval(document.body.innerText +='\nbye')
is not what you want, but here is a (not remended) counterexample:var myvar = 0; var bye = 123 eval(document.body.innerText += '\nbye'); console.log(myvar); // 123
myvar =
- Run
The
Function
constructor is basically likeeval
, but it creates a function instead of running the evaluating the string as code immediately.document.body.innerText += '\n!!!'
can't return a valid string, so it will just throw.Then you have some strange mixes of these functions.
If you pass a function to the
Function
constructor, it will be stringified. TheFunction
constructor will return an anonymous function that will just declare a function like the argument. It's pointless.If you call
toString
, this will stringify the anonymous function.Then,
void(Function(function foo(){document.body.innerText += '\n>hi2'; return true}).toString())();
will attempt to call this stringification. But strings are not callable. Error.And
eval(Function(function foo(){document.body.innerText += '\nbye2'; return true}).toString())();
will evaluate the stringification. Just why? But function declarations don't return a value, so you will just get undefined, which is not callable. Error.And
Function(Function(function foo(){document.body.innerText += '\n!!!2'; return true}).toString())();
will stringifyfoo
, parse it to an anonymous function, stringify the anonymous function, and parse it again to another anonymous function. Please, don't do this. Finally, the call will return undefined because there is no return statement in there.