В чем сходство Function и Eval?
У крокфорда в good parts есть утверждение, что Function -- это, почти то же самое что eval. Я копаюсь уже битый час, и не могу понять вообще, что у них общего. Насколько я понял, Function сразу компилируется в обычную анонимную ф-цию. И в дальнейшем, она ведет себя как обычная ф-ция, даже с сохранением лексического скопа в замыканиях.
Код:
fu=Function("var a=1; return function(){return(a)}") |
Общее то, что они работают со строками, т.е. компилируют строки в JS. Function всегда создаёт глобальные функции, т.е.
var a = 1;
(function () {
var a = 2;
new Function('alert(a)')(); // 1
})();
A eval работает в том контексте, в котором он был вызван.
var a = 1;
(function () {
var a = 2;
eval('alert(a)'); // 2
})();
В 99% случаев лучше использовать Function, т.к. для такого кода также используется JIT компилятор VM, а вот для eval конструкций нет и это может серьёзно сказаться на производительности, а самое страшное то, что вызов eval внутри блока также отменяет использование JIT для всего блока:
// Очень быстрый цикл, т.к. используется JIT
for (var i = 0; i < 1e6; i++) {
console.log(el);
}
// Всё будет очень тормозить, т.к. вызов eval внутри цикла отменил использование JIT для всей конструкции.
for (var i = 0; i < 1e6; i++) {
eval('console.log(el);');
}
|
Цитата:
// Парсинг строки как литерала объекта
var a = '({a: 1, b: 2})';
eval(a); // {a: 1, b: 2}
new Function('return ' + a)(); // {a: 1, b: 2}
// Создание функции из строки (однако следует помнить про то, что у функций будет разный контекст)
eval('(function (a, b) { return a + b; })')(1, 2) // 3
new Function('a', 'b', 'return a + b')(1, 2) // 3
|
var a = '{a: 1, b: 2}';
eval(a); // {a: 1, b: 2}
kobezzza, ёшкин кот, этож классический пример.eval(a); //syntax error |
Цитата:
|
Цитата:
Код:
Код:
a=1 |
Цитата:
Цитата:
Цитата:
ЗЫ: а вообще ты мне надоел, можешь гавнокодить как тебе захочется. |
Цитата:
a=eval("(function(){'test'})") 3: 1267ms |
Цитата:
|
Т.е. ты не видешь, что
Function("test")
и
function(){"test"}
Это разные по функционалу функции?
alert(Function("test").toString())
Более того, на таких убогий тестах вообще нельзя делать никаких выводов. |
Цитата:
Код:
a=eval("(function(){'test'})") |
Цитата:
Для тестов:
var a = [],
b = [];
var f1 = eval('(function (val) { a.push(val); })');
var f2 = new Function('val', 'b.push(val)');
for (var i = 0; i < 1e6; i++) {
f1(i);
}
for (var i = 0; i < 1e6; i++) {
f2(i);
}
Результат будет одинаков, т.к. в обоих случаях элементарное содержимое функций, а если у тебя в теле функций будет сложная логика, вызовы других функций и т.д., то велика вероятность, что встроенный JIT даст значительный профит на варианте с Function, в то время как eval никак не будет обрабатываться. Т.е. твои тесты - убоги и не несут никакой полезной информации. |
Цитата:
Код:
|
Цитата:
// У тебя было
Function("test") // поиск идентификатора test
// А не
Function("'test'") // создание литерала строки 'test'
|
Цитата:
Код:
f1=function(){"test1"} |
foo, слишком толсто, удаляюсь из темы.
|
Цитата:
|
Цитата:
|
kobezzza,
Код:
|
Цитата:
Никто и никогда не будет делать так:
for (...) {
Function('console.log(...)')()
}
Поэтому я и говорю, что твои тесты бессмысленны. Что они тестируют? Скорость компиляции - это не узкое место. Я же говорю про скорость работы полученной функции и привёл пример, где эта скорость одинакова, но пояснил, что она одинакова только в этом частном случае, т.к. у функций слишком простое тело. Я сказал, что во всех современных VM JS используются JIT компиляторы и что конструкции eval не обрабатываются этим самым компилятором, а вот Function обрабатываются. Гугли что такое JIT компилятор и как он работает, может станет понятно. Т.е. чем сложнее тело функции, тем очевиднее разница в скорости функции полученной через Function и eval.
global.a = [];
global.b = [];
function test() {
var f1 = eval('(function (val) { global.a.push(val); })');
var f2 = new Function('val', 'global.b.push(val)');
console.time('start');
for (var i = 0; i < 1e6; i++) {
f1(i);
}
console.timeEnd('start');
console.time('start2');
for (var i = 0; i < 1e6; i++) {
f2(i);
}
console.timeEnd('start2');
}
test();
Вот уже чуть более сложный пример у меня Function при тесте в V8 быстрее в 3 раза. Теперь ты понял? |
Цитата:
|
Цитата:
Чем сложнее тело функции - тем потенциальна выше разница. JIT - это не 100% гарантия, но очень сильная возможность, а eval её полностью исключает. В других VM такой же результат. Пруф видео |
Цитата:
Кстати, я заметил, что второй цикл раз от раза быстрей работает, заметно невооруженным глазом. Там кэширование наверное, на всю катушку работает. Не знаешь, как там кэш сбросить или отключить? |
Цитата:
Цитата:
|
| Часовой пояс GMT +3, время: 23:38. |