eval() evaluates a string of JavaScript code. The Function constructor can be used to create a function from string. Someone says that the Function constructor is another form of eval(). However, one significant difference between eval() and the Function constructor is that while eval() keeps the lexical scope, the Function constructor always creates top-level functions.
function f1() {
var bbb = 2;
eval('alert(bbb);');
}
f1(); //alerts 2
function f2() {
var bbb = 2;
new Function('alert(bbb)')();
}
f2(); //bbb undefined error
function f3() {
var bbb = 2;
eval('function() {alert(bbb);}')();
}
f3(); //alerts 2eval() inside a function body creates a closure while new Function() doesn't. This difference may not bother you for the whole lifetime. However, it happens to bother me once. It's about jQuery - a new type of JavaScript library. I'm using jQuery in my bookmarklet application. In order to make the code as unobtrusive as possible, I decided to put all my code including the jQuery code inside an anonymous function. It looks like this:
(function() {
//jQuery code
//my code
})();In this way, even the jQuery object is just a local variable. The outside environment is completely unaffected. But $().parents(), $().children, $().prev(), $().next() and $().siblings() always fail in my code. These functions are created by the Function constructor in $.grep() and $.map().
// If a string is passed in for the function, make a function
// for it (a handy shortcut)
if ( typeof fn == "string" )
fn = new Function("a","i","return " + fn);
So they are all top-level and the identifier "jQuery" inside is resolved as window.jQuery which is undefined and the code fails.
We can implement an alternative to the Function constructor and use it within the lexical scope:
var createFunc = (function () {
var args = [].slice.call(arguments);
var body = args.pop();
return eval('function(' + args.join(',') + ') {' + body + '}');
}).toString();
function f4() {
var bbb = 2;
eval(createFunc)('alert(bbb);')();
}
f4(); //alerts 2You can use eval(createFunc) just like new Function(), but you get the bonus lexical scope binding.
function f6() {
var add = function(a, b) {return a + b;};
return eval(createFunc)('x', 'y', 'return add(x, y);');
}
f6()(3, 5); //8At last, I quote Douglas Crockford's words on eval() and the Function constructor
"eval is Evil
The eval function is the most misused feature of JavaScript. Avoid it.
eval has aliases. Do not use the Function constructor. Do not pass strings to setTimeout or setInterval. "