Additional notes to Cristian Sanchez' posting.
You can never access local scope vars within a 'Function'-Evaluation.
Lets see the difference between Function and eval.
Function-Example:
var f, a = 1;
(function () {
var a = 123;
f = new Function("return a");
})();
console.log(f()) // 1
The Function-Constructor doesn't know anything about the local scope, because it creates a new isolated Scope underneath the window/global-Object - not at the position where it is - that is the main-difference to eval.
Eval-Example:
var f, a = 1;
(function () {
var a = 123;
eval("f = function() { return a }");
})();
console.log(f()) // 123
'eval' has access to the local vars. Even if you scope the whole thing.
var f, a = 1;
(function () {
var a = 123;
eval("f = (function() { function f() { return a }; return f; })();");
})();
console.log(f()) // still 123
In the following example f() throws an error - "a" is undefined in his own (and global) scope. The Function-Constructor has its own special scope without knowing anything outside - except his parent scope - the window/global-object.
delete a;
var f;
(function ()
{
var a = 1;
f = new Function("return a");
})();
console.log(f()); // Throws error (a is not defined)
If you want to use local vars, pass it as parameters to the Function-Constructor inside the inner scope!
var f, a = 1;
(function () {
var a = 123;
f = new Function("a", "return a");
console.log(f(a)); // passing inner a: result = 123
})();
console.log(f(a)); // passing outer a: result = 1
or
var result, a = 1;
(function () {
var a = 123;
var f = new Function("a", "return a");
result = f(a); // store result in global var
})();
console.log(result); // 123
You can execute Function directly with call/apply, too (no "new" needed).
Function('a','b','c', 'console.log(c,b,a)').call(this, 1, 2, 3); // output: 3 2 1
Function('console.log(arguments)').apply(this, [1, 2, 3]); // access through arguments[0-3]
By the way, it's always recommend, setting the strict mode, to enable correct ES5 behaviour.
With strict-mode 'this' is (correctly) undefined by default - until you bind an object.
Function('console.log(this)')(); // this is 'window' in sloppy mode
Function('"use strict"; console.log(this)')(); // this is undefined - correct behavior
If you want, you can bind 'this' explicitly
// bind 'this' to 'window' again
Function('"use strict";console.log(this)').bind(window)();
// bind 'this' to an Object without __proto__
Function('"use strict";console.log(this)').bind(Object.create(null))();
Of course you can bind any function/class-object to extend objects.
function SomeClass()
{
this.a = 1;
}
var cls = new SomeClass();
new Function('"use strict"; this.a = 5; this.b = 6;').bind(cls)();
console.log(cls.a); // a = 5 - override property
console.log(cls.b); // b = 6 - appended property
Same result with direct call, without 'new' keyword.
function SomeClass()
{
this.a = 1;
}
var cls = new SomeClass();
Function('"use strict"; this.a = 5; this.b = 6; this.foo = function(){console.log("bar")}').call(cls);
console.log(cls.a); // a = 5 - override property
console.log(cls.b); // b = 6 - appended property
console.log(cls.foo()); // bar - appended function
Every function/class is created through the the 'Function'-constructor.
So you don't have to write "Function" in your code. You can use the constructor-object, too.
function SomeClass()
{
this.a = 1;
}
var cls = new SomeClass();
SomeClass.constructor("this.a = 2;").call(cls);
cls; // SomeClass {a: 2}, because "SomeClass.constructor" === Function
The use of 'Function' is good for example for games, if you have a XMLHttpRequest-Preloader, which loads a very large Javascript-File (5-10 MB bundled scripts), while you want display a loading-bar or something else to the user, instead loading the whole thing with a script-tag, while the user is waiting for page-loading without any visual response.
It does not matter if you load a large script via a script tag, or via Function once on startup. The engine has to load the plain code and evaluate it either way. There are no security aspects, if your(!) code came from a trusted source (your domain) and you know whats inside.
'Function' and 'eval' are only bad with untrusted code (when other users have influence on it) or in loops (slow performance due compiling), but it is totally okay to load & evaluate your own scripts on startup, if the code is the same as in external Javascript-files.