Kiedy wdrażałem silnik JScript, zalecałem wydrukowanie koszulki EVAL IS EVIL , ale niestety nigdy się do tego nie zabraliśmy.
Moim największym problemem z eval nie jest oczywisty atak polegający na wstrzykiwaniu złośliwego kodu, choć z pewnością budzi to ogromne zaniepokojenie. Moim największym problemem jest to, że ludzie używają go jako naprawdę dużego młota do rozwiązywania naprawdę małych problemów. Większość rzeczywistych zastosowań, które widziałem na „ewaluacji” na wolności, kiedy pracowałem w zespole JScript, można było w prosty sposób rozwiązać przy użyciu tabeli odnośników; a ponieważ każdy obiekt w JScript jest już tabelą odnośników , nie jest to uciążliwe. Eval ponownie uruchamia kompilator i całkowicie niweczy zdolność kompilatora do optymalizacji kodu .
Aby uzyskać więcej przemyśleń w tym duchu, zobacz moje artykuły z 2003 roku na ten temat:
Ogólne zło:
http://blogs.msdn.com/b/ericlippert/archive/2003/11/01/53329.aspx
Szatańskie ataki wtryskowe:
http://blogs.msdn.com/b/ericlippert/archive/2003/11/04/53335.aspx
eval
tworzenia dużych fragmentów kodu tak, jak lubią aplikacje takie jak JSPacker? JSPacker + gzip zwykle skutkuje mniejszymi rozmiarami plików niż którekolwiek z rozwiązań, ale jak słusznie zauważyłeś, zasadniczo uruchamia kompilator dwa razy na tym samym fragmencie kodu, a także narzuca pewne koszty zastępowania łańcucha.eval()
to nie zagrożenie bezpieczeństwa na klienta (przeglądarki) kodu.Większość dziur w zabezpieczeniach to te same dziury, co w przypadku wstrzykiwania SQL, a mianowicie łączenie danych wejściowych użytkownika z kodem JavaScript. Różnica polega na tym, że chociaż istnieją sposoby, aby upewnić się, że tak się nie stanie z SQL, niewiele można zrobić z JavaScript.
Jako trywialny i bezużyteczny przykład uproszczony kalkulator JavaScript:
Jednym z poprawnych przykładów użycia są niektóre programy pakujące JavaScript, które kompresują JavaScript, wyciągając typowe słowa i zastępując je krótkimi 1-2 znakowymi zamiennikami. Pakowacz wyprowadza to wszystko wraz z kodem zastępującym ciąg znaków na podstawie wygenerowanego słownika, a następnie sprawdza wynik.
źródło
Są pewne rzeczy, które są niemożliwe do zrobienia w JS bez funkcji eval (podobny
eval
,Function
i być może więcej).Weźmy
apply
na przykład. Jest łatwy w użyciu, gdy używasz go do zwykłych wywołań funkcji:foo.apply(null, [a, b, c])
Ale jak byś to zrobił dla obiektów tworzonych za pomocą nowej składni?
new Foo.apply(null, [a, b, c])
nie działa, ani nie robi podobnych form.Ale możesz obejść to ograniczenie za pomocą
eval
lubFunction
(używamFunction
w tym przykładzie):Przykład:
Foo.New.apply(null, [a, b, c])
;Oczywiście można ręcznie budować używane funkcje
Function.prototype.New
, ale nie tylko jest to pełne i niezgrabne, ale (z definicji) musi być skończone.Function
umożliwia działanie kodu dla dowolnej liczby argumentów.źródło
eval()
? ”Nieco bezpośrednią odpowiedzią z mojej strony było opracowanie obszaru testowania API zorientowanego na programistów. Daliśmy obszar tekstowy na stronie i przycisk Uruchom. Centralny punkt strony polegał na tym, że mogli wypróbować rzeczy w JavaScript w stosunku do naszego interfejsu API komunikującego się z iframe, co nie było tak łatwe w lokalnym środowisku.
Cokolwiek złośliwego, co można było zrobić w tym przypadku, mogło być również zrobione przez programistę otwierającego swoje narzędzia F12.
źródło
Zgadzam się, że należy go bardzo rzadko używać, ale znalazłem potężny przypadek użycia
eval
.W Firefoksie jest eksperymentalna nowa funkcja o nazwie asm.js, nad którą pracuję. Pozwala to na skompilowanie ograniczonego podzbioru języka JavaScript w natywny kod. Tak, to jest bardzo niesamowite, ale ma ograniczenia. Możesz myśleć o ograniczonym podzbiorze Javascript jako języku podobnym do C osadzonym w Javascript. Tak naprawdę nie jest przeznaczony do czytania ani pisania przez ludzi.
Ten ograniczony podzbiór Javascript nie pozwala mi wstrzykiwać mojego kodu wygenerowanego w środowisku wykonawczym do skompilowanego kodu po jego skompilowaniu.
Napisałem jakiś kod, który pozwala użytkownikowi na zapisanie, w znanym zapisie, wyrażenia matematycznego i konwersję w locie do kodu asm.js. O ile nie chcę, aby kod był przetwarzany po stronie serwera (czego nie robię),
eval
jest to jedyne narzędzie, które pozwala mi przetwarzać wynikowy kod przez przeglądarkę w czasie rzeczywistym.źródło
Jak zauważyli inni, najważniejszą rzeczą podczas pracy
eval
jest zapewnienie bezpieczeństwa. W tym celu chcesz dokładnie sprawdzić argumenty i zachowaćeval
prosty kod, ponieważ generalnie trudniej jest utrzymać i zabezpieczyć kod wygenerowany w czasie wykonywania.Biorąc to pod uwagę, lubię korzystać
eval
z dwóch rodzajów rzeczy (nawet jeśli prawdopodobnie byłyby lepsze, mniej szatańskie alternatywy):eval
jest to sposób „jawnego buforowania kodu”, można go wykorzystać do poprawy wydajności. Pamiętaj, że optymalizatory są zawsze ulepszane, ale po prostu nie ma gwarancji, co mogą dla Ciebie zrobić. Wyrażając rzeczy w kodzie, faktycznie możesz pomóc optymalizatorowi w podejmowaniu mądrzejszych decyzji.Na przykład to wstępnie skompilowane podejście do iteratora obiektów wykazuje wyraźne korzyści w zakresie wydajności podczas
eval
iteracji właściwości obiektu. Pokazuje także początki potężnego systemu typów, który może zapewnić ukryte sprawdzanie ograniczeń i wiele więcej, za niewielką opłatą.Wielu doświadczonych programistów Javascript prawdopodobnie zwróciłoby uwagę, że jest to wielka dziura, ponieważ jeśli zaczniesz pisać JavaScript w ten sposób, zasadniczo zmienisz sposób korzystania z języka. To jednak niekoniecznie musi być złą rzeczą dla tych, którzy lubią Javascript, ale brakuje im także podstawowych funkcji językowych, które można osiągnąć jedynie poprzez zmianę sposobu, w jaki korzystamy z samego języka.
źródło
Mam sytuację, w której eval wygląda jak droga, oceniając ciąg i zwracając istniejącą zmienną, której nazwa jest taka sama jak ciąg.
Mam kilka tabel: table1ResultsTable, table2ResultsTable, tableNResultsTable. Mam zmienne skonfigurowane o tych samych nazwach, które są obiektami danych jQuery. Używam ich do konfigurowania tabel i wywoływania na nich funkcji danych jQuery.
Każda tabela ma przypisaną klasę = „resultsTable”. Teraz muszę uzyskać zmienną po kliknięciu tabeli. Robię to:
Dostaję więc identyfikator tabeli, w której kliknięto komórkę, która ma taką samą nazwę jak odpowiadająca jej zmienna obiektu danych. Jeśli ktoś ma sugestię dotyczącą ulepszenia, chciałbym o tym wiedzieć.
źródło
event.target.parentElement.parentElement.parentElement
jest przerażające. Ponadto spodziewam się, że wywołanie eval wygeneruje błąd „błąd referencyjny: [id] nie jest zdefiniowany”, chyba że celowo używasz identyfikowalnych identyfikatorów (który jest zepsuty, zły i może spowodować dziwne rzeczy, jeśli skończysz generowanie duplikatów identyfikatorów).document.getElementById(ID).MySpecialProperty = MYSPECIALPROPERTYVALUE
(nie wspominając, że to też świetne, ale jest lepsze niż eval). Jak zauważa Eric Lippert, „każdy obiekt w JScript jest już tabelą odnośników”.