Czy te dwie funkcje robią to samo za kulisami? (w funkcjach pojedynczych instrukcji)
var evaluate = function(string) {
return eval('(' + string + ')');
}
var func = function(string) {
return (new Function( 'return (' + string + ')' )());
}
console.log(evaluate('2 + 1'));
console.log(func('2 + 1'));
javascript
function
optimization
eval
qwertymk
źródło
źródło
new
rozważane w tej dyskusji?Function
niejawnie tworzy wystąpienie plikufunction object
. Wykluczenie wnew
ogóle nie zmieni kodu. Oto jsfiddle demonstrujące, że: jsfiddle.net/PcfG8Odpowiedzi:
Nie, to nie to samo.
eval()
ocenia ciąg jako wyrażenie JavaScript w bieżącym zakresie wykonania i może uzyskać dostęp do zmiennych lokalnych.new Function()
analizuje kod JavaScript przechowywany w ciągu znaków na obiekt funkcji, który można następnie wywołać. Nie może uzyskać dostępu do zmiennych lokalnych, ponieważ kod działa w oddzielnym zakresie.Rozważ ten kod:
function test1() { var a = 11; eval('(a = 22)'); alert(a); // alerts 22 }
Gdyby
new Function('return (a = 22);')()
została użyta, zmienna lokalnaa
zachowałaby swoją wartość. Niemniej jednak niektórzy programiści JavaScript, tacy jak Douglas Crockford, uważają, że nie należy ich używać, chyba że jest to absolutnie konieczne , a ewaluacja / używanieFunction
konstruktora na niezaufanych danych jest niebezpieczne i nierozsądne.źródło
new Function(code)
jest to to samo,eval('(function(){'+code+'})()')
czy jest to zupełnie nowy kontekst wykonania?eval('(function(){'+code+'})')
, co zwróci obiekt funkcji. Według MDN , „Funkcje utworzone za pomocą konstruktora Function nie tworzą domknięć do swoich kontekstów tworzenia; zawsze działają w kontekście okna (chyba że treść funkcji zaczyna się od instrukcji„ use strict ”; w takim przypadku kontekst jest niezdefiniowany) ”.Nie.
W twojej aktualizacji wywołania
evaluate
ifunc
dają ten sam wynik. Ale z całą pewnością nie „robią tego samego za kulisami”.func
Funkcja tworzy nową funkcję, ale potem natychmiast wykonuje go, podczas gdyevaluate
funkcja po prostu wykonuje kod na miejscu.Z pierwotnego pytania:
var evaluate = function(string) { return eval(string); } var func = function(string) { return (new Function( 'return (' + string + ')' )()); }
Dają one bardzo różne wyniki:
evaluate('0) + (4'); func('0) + (4');
źródło
return eval('(' + string + ')');
wtedy, przyniosłyby takie same wyniki.new Function
tworzy funkcję, której można użyć ponownie.eval
po prostu wykonuje podany ciąg i zwraca wynik ostatniej instrukcji. Twoje pytanie jest błędne, gdy próbowałeś utworzyć funkcję opakowującą, która używa funkcji do emulacji wartości eval.Czy to prawda, że za zasłonami mają wspólny kod? Tak, bardzo prawdopodobne. Dokładnie ten sam kod? Nie, na pewno.
Dla zabawy, oto moja własna niedoskonała implementacja wykorzystująca eval do tworzenia funkcji. Mam nadzieję, że rzuca trochę światła na różnicę!
function makeFunction() { var params = []; for (var i = 0; i < arguments.length - 1; i++) { params.push(arguments[i]); } var code = arguments[arguments.length - 1]; // Creates the anonymous function to be returned // The following line doesn't work in IE // return eval('(function (' + params.join(',')+ '){' + code + '})'); // This does though return eval('[function (' + params.join(',')+ '){' + code + '}][0]'); }
Największą różnicą między tą a nową funkcją jest to, że funkcja nie ma zakresu leksykalnego. Więc nie miałby dostępu do zmiennych zamykających, a mój miałby.
źródło
arguments.slice()
zamiast pętli for? Lub jeśli argumenty nie jest prawdziwym tablicą[].slice.call(arguments, 1)
.Chcę tylko wskazać jakąś składnię używaną w przykładach tutaj i co to oznacza:
var func = function(string) { return (new Function( 'return (' + string + ')' )()); }
zwróć uwagę, że funkcja (...) () ma na końcu znak „()”. Ta składnia spowoduje, że func wykona nową funkcję i zwróci ciąg, a nie funkcję zwracającą ciąg, ale jeśli użyjesz następującego:
var func = function(string) { return (new Function( 'return (' + string + ')' )); }
Teraz func zwróci funkcję, która zwraca ciąg.
źródło
Jeśli masz na myśli, czy przyniesie to te same wyniki, to tak ... ale samo oszacowanie (inaczej „oszacuj ten ciąg JavaScript”) byłoby znacznie prostsze.
EDYTUJ poniżej:
To tak, jakby powiedzieć ... czy te dwa zadania matematyczne są takie same:
1 + 1
1 + 1 + 1 - 1 + 1 - 1 * 1/1
źródło
Function
obiekt prawdopodobnie przechowuje ciąg w prywatnej zmiennejeval
składowej, aby wywołać funkcję.W tym przykładzie wyniki są takie same, tak. Oba wykonują przekazane wyrażenie. To właśnie czyni je tak niebezpiecznymi.
Ale robią różne rzeczy za tym poczuciem. Ten
new Function()
, który jest zakulisowy, tworzy anonimową funkcję na podstawie dostarczonego kodu, która jest wykonywana, gdy funkcja jest wywoływana.JavaScript, który do niego przekazujesz, technicznie nie jest wykonywany, dopóki nie wywołasz funkcji anonimowej. W przeciwieństwie do tego,
eval()
który wykonuje kod od razu i nie generuje funkcji na jego podstawie.źródło
Does the Function() one use another stack call level than eval?
: Tak przypuszczam, ponieważeval()
nie tworzy funkcji na podstawie danych wejściowych - po prostu ją wykonuje.new Function()
tworzy nową funkcję, którą następnie wywołuje.