Дополнительные примечания к проводке Cristian Санчеса».
Вы никогда не сможете получить доступ к локальным областям видимости в рамках «функции-оценки».
Позволяет увидеть разницу между функцией и eval.
Функционально-Пример:
var f, a = 1;
(function() {
var a = 123;
f = new Function("return a");
})();
console.log(f()) // 1
Функция-конструктор ничего не знаю о локальной области видимости, не знает, потому что он создает новый изолированный Scope под окном/глобальный-объект - не в том месте, где его - это основное отличие от eval.
Eval-Пример:
var f, a = 1;
(function() {
var a = 123;
eval("f = function() { return a }");
})();
console.log(f()) // 123
'Eval' имеет доступ к местному Варсу. Даже если вы охватите все это.
var f, a = 1;
(function() {
var a = 123;
eval("f = (function() { function f() { return a }; return f; })();");
})();
console.log(f()) // still 123
В следующем примере F() выдает ошибку - "а" не определено в его собственной (и глобальной) области. Функция-конструктор имеет свой собственный специальный объем, не зная ничего снаружи, кроме его родительской области - окна/глобального объекта.
delete a;
var f;
(function()
{
var a = 1;
f = new Function("return a");
})();
console.log(f()); // Throws error (a is not defined)
Если вы хотите использовать местный ВАР, передать его в качестве параметров функции-конструктора внутри внутренней рамки!
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
или
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
Вы не можете выполнять функции непосредственно вызова/применить, тоже (не "новый" требуется).
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]
Кстати, это всегда рекомендуется, установив строгий режим, чтобы обеспечить правильное поведение ES5.
С строгим режимом «это» (правильно) undefined по умолчанию - пока вы не привяжете объект.
Function('console.log(this)')(); // this is 'window' in sloppy mode
Function('"use strict"; console.log(this)')(); // this is undefined - correct behavior
Если вы хотите, вы можете связать «это» явно
// 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))();
Конечно, вы можете связать любую функцию/класс-объект для расширения объектов.
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
Тот же результат с прямым вызовом, без «нового» ключевого слова.
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
Каждая функция/класс создается через конструктор «Function».
Значит, вам не нужно писать «Функция» в вашем коде. Вы также можете использовать объект-конструктор.
function SomeClass()
{
this.a = 1;
}
var cls = new SomeClass();
SomeClass.constructor("this.a = 2;").call(cls);
cls; // SomeClass {a: 2}, because "SomeClass.constructor" === Function
Использование «Function» хорошо, например, для игр, если у вас есть XMLHttpRequest-Preloader, который загружает очень большой JavaScript-файл (5-10 Мб в комплекте скриптов), в то время как вы хотите отобразить загрузочный бар или что-то еще для пользователя, вместо этого загружая все это с помощью тега script, в то время как пользователь ждет загрузки страницы без какого-либо визуального ответа.
Неважно, если вы загружаете большой скрипт через тег скрипта или через функцию один раз при запуске. Двигатель должен загружать простой код и оценивать его в любом случае. Нет никаких аспектов безопасности, если ваш (!) Код поступает из надежного источника (вашего домена), и вы знаете, что внутри.
«Функция» и «eval» являются плохими только с ненадежным кодом (когда на него влияют другие пользователи) или в циклах (медленная производительность при компиляции), но вполне нормально загружать & оценивать свои собственные сценарии при запуске , если код такой же, как во внешних Javascript-файлах.
См.: [Законное использование конструктора функций] (http://stackoverflow.com/questions/3026089/legitimate-uses-of-the-function-constructor) – CMS
Хорошее видео о функциях javascript http: // developer. yahoo.com/yui/theater/video.php?v=crockonjs-3 – Thomas
@CMS @Thomas, Спасибо за ссылки. – c4il