JavaScript eval işlevini kullanmak neden kötü bir fikirdir?


534

Eval işlevi dinamik olarak kod oluşturmak için güçlü ve kolay bir yoludur, bu yüzden uyarılar nelerdir?


92
Simon Willison tarafından değerlendirme () - 24ways.org/2005/dont-be-eval
Brian Singh

5
Moduscreate.com/javascript-performance-tips-tricks - (new Function (str)) () öğesinde belirtildiği gibi eval (str) 'den daha performanslıdır. Sadece 2 sent :)
Grgur

3
Görünüşe göre yeni fcuntion (a) kromdaki eval (a) 'dan% 67 daha yavaş
uyku nedir

benim için yeni fonksiyonlar (a) osx üzerinde% 80 daha yavaş son krom
john Smith

3
Performansı karşılaştırmak için statik bir işlev ekledim. jsperf.com/eval-vs-new-function/2
Nepoxx

Yanıtlar:


386
  1. Uygunsuz kullanımı eval enjeksiyon saldırıları için kodunuzu açılıyor

  2. Hata ayıklama daha zor olabilir (satır numarası vb. Yok)

  3. değerlendirilen kod daha yavaş çalışır (değerlendirilen kodu derleme / önbellekleme fırsatı yoktur)

Düzenleme: @Jeff Walden yorumlarda belirtildiği gibi, # 3 bugün 2008 yılında olduğundan daha az doğrudur. Ancak, derlenmiş komut dosyalarının bazı önbelleğe alma olsa da, bu sadece hiçbir değişiklik ile tekrar değerlendirilen komut dosyaları ile sınırlı olacaktır. Daha olası bir senaryo, her seferinde küçük değişiklikler yapılan ve bu nedenle önbelleğe alınamayan komut dosyalarını değerlendiriyor olmanızdır. Diyelim ki BAZI değerlendirilen kod daha yavaş çalışıyor.


2
@ Jeffeffalden, harika yorum. Yayınınızdan bir yıl geçtiğini fark etsem de yazımı güncelledim. Xnzo72, yorumunuzu bir şekilde nitelendirdiyseniz (Jeff'in yaptığı gibi) o zaman sizinle aynı fikirde olabilirim. Jeff şu noktaya dikkat çekti: "Aynı dizenin birden çok kez değerlendirilmesi yükü ayrıştırmayı önleyebilir". Olduğu gibi, sadece yanılıyorsunuz; # 3 birçok senaryo için geçerlidir.
Prestaul

7
@Prestaul: Sözde saldırgan, istemcideki JavaScript'i değiştirmek için hangi geliştirici aracını kullanabileceğinden, Eval () kodunuzu enjeksiyon saldırılarına neden açtığını söylüyorsunuz? Henüz açılmadı mı? (Tabii ki müşteri JavaScript'i hakkında konuşuyorum)
Eduardo Molteni

60
@EduardoMolteni, kullanıcıların kendi tarayıcılarında js çalıştırmalarını umursamıyoruz (ve gerçekten engelleyemiyoruz). Kaçınmaya çalıştığımız saldırılar, kullanıcı tarafından sağlanan değerlerin kaydedilmesi, daha sonra javascript'e yerleştirilmesi ve değerlendirilmesidir. Örneğin, kullanıcı adımı şu şekilde ayarlayabilirim: badHackerGuy'); doMaliciousThings();ve kullanıcı adımı alırsanız, bir komut dosyasına yapıştırabilir ve başkalarının tarayıcılarında değerlendirebilirim, o zaman makinelerinde istediğim herhangi bir javascript'i çalıştırabilirim (örneğin, yayınlarımı + 1'lemeye zorlayın, verilerini sunucumda yayınlama vb.)
Prestaul

3
Genel olarak, çoğu işlev çağrısı olmasa bile # 1 oldukça fazla doğrudur. eval () tecrübesiz programcılar tarafından istismar edilmemeli ve tecrübesiz programcılar tarafından istismar edilmemelidir. Bununla birlikte, deneyimli programcılar genellikle kodlarında daha iyi bir mimariye sahiptir ve eval () bu daha iyi mimari nedeniyle nadiren gerekli veya hatta düşünülecektir.
frodeborli

4
@TamilVendhan Elbette kesme noktaları koyabilirsiniz. Değerlendirilen kodunuz için Chrome tarafından oluşturulan sanal dosyaya, debugger;ifadeyi kaynak kodunuza ekleyerek erişebilirsiniz . Bu, programınızın bu satırda yürütülmesini durduracaktır. Sonra bundan sonra başka bir JS dosyası gibi hata ayıklama kesme noktaları ekleyebilirsiniz.
Sid

346

eval her zaman kötü değildir. Mükemmel uygun olduğu zamanlar vardır.

Bununla birlikte, eval şu ​​anda ve tarihsel olarak ne yaptığını bilmeyen insanlar tarafından aşırı derecede kullanılıyor. Bu, ne yazık ki JavaScript öğreticileri yazan kişileri içerir ve bazı durumlarda bunun gerçekten güvenlik sonuçları olabilir - veya daha sıklıkla basit hatalar. Dolayısıyla, eval üzerine soru işareti atmak için ne kadar çok şey yapabilirsek, o kadar iyidir. Eval'i her kullandığınızda, ne yaptığınızı kontrol etmelisiniz, çünkü şansınızı daha iyi, daha güvenli ve daha temiz bir şekilde yapıyor olabilirsiniz.

Çok tipik bir örnek vermek için, 'patates' değişkeninde kimliği olan bir öğenin rengini ayarlamak için:

eval('document.' + potato + '.style.color = "red"');

Yukarıdaki kod türünün yazarları, JavaScript nesnelerinin nasıl çalıştığının temelleri hakkında bir ipucu verselerdi, gerçek nokta isimleri yerine köşeli parantezlerin kullanılabileceğini fark etmişlerdi:

document[potato].style.color = 'red';

... okunması çok daha kolay ve daha az potansiyel olan buggy.

(Ama sonra, ne yaptığını / gerçekten bilen biri şöyle der:

document.getElementById(potato).style.color = 'red';

bu da DOM öğelerine doğrudan belge nesnesinden erişmenin tehlikeli eski numarasından daha güvenilirdir.)


82
Hmm, sanırım ilk JavaScript öğrenirken şanslıydım. Ben her zaman DOM erişmek için "document.getElementById"; ironik olarak, sadece o zaman yaptım çünkü nesnelerin JavaScript'te nasıl çalıştığı hakkında bir fikrim yoktu ;-)
Mike Spross

5
Katılıyorum. Bazen eval tamam örn.
Web servislerinden

40
@schoetbi: JSON JSON.parse()yerine kullanmamalısınız eval()?
nyuszika7h

4
@bobince code.google.com/p/json-sans-eval , tüm tarayıcılarda çalışmalarını yapar github.com/douglascrockford/JSON-js . Doug Crockford'un json2.js, değerlendirmeyi dahili olarak kullanıyor, ancak kontrollerle. Ayrıca, JSON için yerleşik tarayıcı desteği ile ileri uyumludur.
Martijn

8
@bobince Eksik JSON kütüphanelerini ve diğer şeyleri işlemek için özellik algılama ve çoklu dolgular adı verilen bir şey var ( modernizr.com'a bakın )
MauganRa

37

Bir dize herhangi bir JavaScript işlevini çalıştırabilirsiniz çünkü inanıyorum. Bunu kullanmak, kullanıcıların uygulamaya haydut kod eklemesini kolaylaştırır.


5
O zaman alternatif nedir?
modernler

5
Gerçekten alternatif sadece gerektirmeyen kod yazmaktır. Crockford bu konuda uzun sürüyor ve kullanmanız gerekiyorsa, hemen hemen bir program tasarım hatası olduğunu ve yeniden işlenmesi gerektiğini söylüyor. Aslında ben de ona katılıyorum. Tüm kusurları için JS gerçekten esnektir ve esnek hale getirmek için çok fazla alan sağlar.
kemiller2002

3
Doğru değil, çoğu çerçevenin JSON ayrıştırma yöntemi vardır ve bir çerçeve kullanmıyorsanız JSON.parse () kullanabilirsiniz. Çoğu tarayıcı bunu destekler ve eğer gerçekten bir tutamdaysanız, JSON için bir ayrıştırıcıyı kolayca yazabilirsiniz.
kemiller2002

6
Bu argümanı satın almıyorum, çünkü zaten bir Javascript uygulamasına hileli kod enjekte etmek kolaydır. Tarayıcı konsollarımız, komut dosyası uzantılarımız vb. Var. İstemciye gönderilen her kod parçası, istemcinin yürütmesi için isteğe bağlıdır.
user2867288

6
Mesele şu ki, tarayıcınıza kod eklemem daha kolay. Diyelim ki bir sorgu dizesinde eval kullanıyorsunuz. Sorgu dizem eklenmiş olarak o siteye giden bir bağlantıyı tıklatmanızı sağlıyorsam, şimdi kodumu makinenizde tarayıcıdan tam izin alarak yürüttüm. Bu siteye yazdığınız her şeyi günlüğe kaydetmek ve bana göndermek mi istiyorsunuz? Bitti ve beni durdurmak için hiçbir yolu çünkü eval yürütülürken, tarayıcı en yüksek yetki verir.
kemiller2002

27

İki nokta akla geliyor:

  1. Güvenlik (ancak kendiniz değerlendirilmek üzere dizeyi oluşturduğunuz sürece bu sorun olmayabilir)

  2. Performans: yürütülecek kod bilinmiyor olana kadar optimize edilemez. (javascript ve performans hakkında kesinlikle Steve Yegge'in sunumu )


9
İstemci istediği kodla yine de yapabiliyorsa neden güvenlik bir sorundur? Araba tamircisi ?
Paul Brewczynski

2
@PaulBrewczynski, güvenlik sorunu, A kullanıcısı kodun bir kısmını işlenecek şekilde kaydettiğinde ortaya çıkar evalve daha sonra bu küçük kod parçası kullanıcının B tarayıcısında çalışır
Felipe Pereira

21

Eval () öğesine kullanıcı girdisinin iletilmesi bir güvenlik riskidir, ancak eval () 'nin her çağrılması JavaScript yorumlayıcısının yeni bir örneğini oluşturur. Bu bir kaynak domuzu olabilir.


27
Bunu cevapladığımdan sonraki 3 yıl içinde, diyelim ki, ne olduğuna dair anlayışım derinleşti. Aslında olan, yeni bir yürütme bağlamının yaratılmasıdır. Bkz. Dmitrysoshnikov.com/ecmascript/chapter-1-execution-contexts
Andrew Hedges

20

Bu genellikle yalnızca eval kullanıcı girdisini geçiyorsanız bir sorundur.


16

Temel olarak, bakımı ve hata ayıklaması çok daha zordur. Bir gibi goto. Bunu kullanabilirsiniz, ancak daha sonra değişiklik yapması gerekebilecek kişilerde sorun bulmayı zorlaştırır ve zorlaştırır.


Eval, şablonlar gibi eksik meta programlama özelliklerini değiştirmek için kullanılabilir. Kompakt jeneratörü, işlevler üzerindeki sonsuz işlev listesinden daha fazla seviyorum.
16:47

Dize kullanıcıdan gelmediği veya tarayıcıyla sınırlı olduğu sürece. JavaScript, prototipleri değiştirme, obj [üye], Proxy, json.parse, pencere, dekoratör işlevleri (zarflar), burada newf = dekoratör (oldf), Array.prototype.map (f) gibi daha üst düzey işlevler gibi metaprogramlama gücüne sahiptir. , bağımsız değişkenleri diğer işlevlere geçirme, {} ile anahtar kelime bağımsız değişkenleri. Bana eval yerine bunları yapamayacağınız bir kullanım durumu söyleyebilir misiniz?
aoeu256

13

Akılda tutulması gereken bir şey, başka bir şekilde kısıtlanmış bir ortamda kod yürütmek için eval () kullanabileceğinizdir - belirli JavaScript işlevlerini engelleyen sosyal ağ siteleri bazen bir eval blokunda parçalanarak kandırılabilir -

eval('al' + 'er' + 't(\'' + 'hi there!' + '\')');

Dolayısıyla, başka türlü izin verilmeyebilecek bir JavaScript kodu çalıştırmak istiyorsanız ( Myspace , sana bakıyorum ...) o zaman eval () yararlı bir hile olabilir.

Bununla birlikte, yukarıda belirtilen tüm nedenlerden ötürü, tam kontrolünüz olan kendi kodunuz için kullanmamalısınız - sadece gerekli değildir ve 'zor JavaScript saldırıları' rafına daha iyi bir şekilde ayrılmıştır.


1
Sadece yukarıdaki kodu güncelleme .. --hi orada! - bir dize olduğu gibi tırnak içinde olması gerekir. eval ('al' + 'er' + 't (' + '"merhaba!"' + ')');
Mahesh

2
[]["con"+"struc"+"tor"]["con"+"struc"+"tor"]('al' + 'er' + 't(\'' + 'hi there!' + '\')')()
Konrad Borowski

4
Evet, alert'ü () kısıtlayan ancak eval () 'a izin veren sosyal ağ siteleri vardı ?!
joshden

12

Dinamik bir içeriği (cgi veya giriş yoluyla) değerlendirmenize () izin vermedikçe, sayfanızdaki diğer tüm JavaScriptler kadar güvenli ve sağlamdır.


Bu doğru olsa da - içeriğiniz dinamik değilse , eval için hiç bir neden yoktur? Kodu bir işleve koyabilir ve onun yerine çağırabilirsiniz!
Periata Breatta

Sadece örneğin - Ajax çağrısından gelen dönen değeri (JSON benzeri, sunucu tanımlı dizeler vb.) Ayrıştırmak için.
Thevs

2
Ah anlıyorum. Bu dinamiği derdim çünkü müşteri ne olduğunu önceden bilmiyor, ama şimdi ne demek istediğini anlıyorum.
Periata Breatta

7

Cevapların geri kalanıyla birlikte, eval ifadelerinin ileri düzeyde minimizasyona sahip olabileceğini düşünmüyorum.


6

Olası bir güvenlik riskidir, farklı bir yürütme kapsamına sahiptir ve kodun yürütülmesi için tamamen yeni bir komut dosyası ortamı oluşturduğundan oldukça verimsizdir. Daha fazla bilgi için buraya bakın: eval .

Yine de oldukça kullanışlıdır ve ılımlılıkla birlikte kullanıldığında çok sayıda iyi işlevsellik katabilir.


5

Değerlendirilmekte olan kodun güvenilir bir kaynaktan (genellikle kendi uygulamanızdan)% 100 emin olmadığınız sürece, sisteminizi siteler arası komut dosyası saldırılarına maruz bırakmanın kesin bir yoludur.


1
Yalnızca sunucu tarafı güvenliğiniz berbatsa. İstemci tarafı güvenlik saçmalıktır.
doubleOrt

5

Bu tartışma eski biliyorum ama gerçekten böyle bu Google tarafından yaklaşımı ve bu duyguyu başkalarıyla paylaşmak istedim;)

Başka bir şey daha iyi olsun Daha fazla anlamaya çalışın ve nihayet sadece bir şey söylediği için bir şey iyi ya da kötü olduğuna inanmıyorsunuz :) Bu çok daha ilham verici bir video . :) İYİ UYGULAMALAR iyidir, ama onları dikkatsizce kullanmayın :)


1
Evet. Şimdiye kadar en azından Chrome'da, daha verimli gibi görünen bir kullanım durumu buldum. Her yinelemede belirli bir değişkende dize oluşturan bir RAF çalıştırın. Bu dizede yalnızca dönüşümleri ayarlamak, vb. Gibi grafik yönelimli şeyleri ayarlamak için setInterval kullanın. Bir dizi işlevleri arasında döngü veya yalnızca değiştirilen öğeler için dönüşümleri ayarlamak için bir değişken kullanma gibi birçok yaklaşım denedim, ancak şimdiye kadar bu en verimli gibi görünüyor. Animasyon söz konusu olduğunda, en gerçek tezgah testi gözlerinizdir.
jdmayfield

5

Hangi bağlamda kullandığınızı bilmeniz şart değildir.

Uygulamanız, XMLHttpRequest'ten kendi sitenize eval()geri gelen ve güvenilen sunucu tarafı kodunuz tarafından oluşturulan bir JSON'dan bir nesne oluşturmak için kullanıyorsa , bu muhtemelen bir sorun değildir.

Güvenilmeyen istemci tarafı JavaScript kodu zaten bunu yapamaz. Yaptığınız şeyin eval()makul bir kaynaktan gelmesi koşuluyla, sorun yok.


3
Eval kullanmak sadece JSON ayrıştırmaktan daha yavaş değil mi?
Brendan Long

@Qix - tarayıcımda o testi çalıştıran (Krom 53) gösterileri eval olarak biraz daha hızlı parse .
Periata Breatta

@PeriataBreatta Ha, garip. Nedenini merak ediyorum. O zaman ben böyle olmadığını yorumladı. Bununla birlikte, Chrome'un çalışma zamanının belirli alanlarında sürümden sürüme garip performans artışı elde etmek duyulmuyor.
Qix - MONICA

Burada biraz eski bir iş parçacığı, ama okuduğumdan - kendimi geri izlediğimi iddia etmiyorum - JSON.parse aslında eval son aşamada girdi. Böylece verimlilik açısından daha fazla çalışma / zaman alır. Ama güvenlik açısından, neden sadece ayrıştırmıyorsunuz? eval harika bir araçtır. Başka yolu olmayan şeyler için kullanın. İşlevleri JSON üzerinden geçirmek için, bunu eval olmadan yapmanın bir yolu vardır. JSON.stringify'daki bu ikinci parametre, bir işlev olup olmadığını typeof ile kontrol edebileceğiniz bir geri arama çalıştırmanıza olanak tanır. Sonra işlevin .toString () yöntemini edinin. Arama yaparsanız bu konuda bazı iyi makaleler var.
jdmayfield


4

Kullanıcının bazı mantıksal işlevler girmesini ve VE VEYA için değerlendirmesini istiyorsanız, JavaScript değerlendirme işlevi mükemmeldir. İki dizeyi kabul edebilirim eval(uate) string1 === string2, vb.


Function () {} işlevini de kullanabilirsiniz, ancak kullanıcıların sunucunuzu devralmasını istemediğiniz sürece bunları sunucuda kullanırken dikkatli olun. Hahahah.
aoeu256

3

Kodunuzda eval () kullanımını tespit ederseniz, “eval () kötü” mantrasını hatırlayın.

Bu işlev isteğe bağlı bir dize alır ve JavaScript kodu olarak yürütür. Söz konusu kod önceden biliniyorsa (çalışma zamanında belirlenmez), eval () kullanmak için bir neden yoktur. Kod çalışma zamanında dinamik olarak oluşturulursa, eval () olmadan hedefe ulaşmak için genellikle daha iyi bir yol vardır. Örneğin, dinamik özelliklere erişmek için sadece köşeli parantez gösterimini kullanmak daha iyi ve daha basittir:

// antipattern
var property = "name";
alert(eval("obj." + property));

// preferred
var property = "name";
alert(obj[property]);

eval()Ayrıca, kurcalanan kodu (örneğin ağdan geliyor) çalıştırıyor olabileceğiniz için kullanmanın güvenlik etkileri de vardır. Bu, bir Ajax isteğinden gelen JSON yanıtıyla uğraşırken yaygın bir antipatterndir. Bu durumlarda, güvenli ve geçerli olduğundan emin olmak için JSON yanıtını ayrıştırmak için tarayıcıların yerleşik yöntemlerini kullanmak daha iyidir. Desteklemeyen tarayıcılar içinJSON.parse()Yerel olarak JSON.org adresinden bir kütüphane kullanabilirsiniz.

Bu o geçen dizeleri hatırlamak da önemlidir setInterval(), setTimeout()ve Function()yapıcı kullanmaya benzer çoğunlukla için olduğunu eval()ve bu nedenle kaçınılmalıdır.

Sahne arkasında, JavaScript'in programlama kodu olarak ilettiğiniz dizeyi değerlendirmesi ve yürütmesi gerekir:

// antipatterns
setTimeout("myFunc()", 1000);
setTimeout("myFunc(1, 2, 3)", 1000);

// preferred
setTimeout(myFunc, 1000);
setTimeout(function () {
myFunc(1, 2, 3);
}, 1000);

Yeni Function () yapıcısını kullanmak eval () işlevine benzer ve dikkatle yaklaşılmalıdır. Güçlü bir yapı olabilir, ancak sıklıkla yanlış kullanılır. Kesinlikle kullanmanız gerekiyorsa eval(), bunun yerine yeni İşlev () kullanmayı düşünebilirsiniz.

Yeni Function () içinde değerlendirilen kod yerel bir işlev kapsamında çalışacağı için küçük bir potansiyel fayda vardır, bu nedenle değerlendirilmekte olan kodda var ile tanımlanan değişkenler otomatik olarak global olmayacaktır.

Otomatik globalleri önlemenin bir başka yolu da eval()çağrıyı hemen bir işleve sarmaktır .


Eval olmadan bir fonksiyon-yerel dinamik değişken adını nasıl değerlendirebileceğimi önerebilir misiniz? Eval (ve benzeri) fonksiyonları, onları içeren çoğu dilde son çaredir, ancak bazen gereklidir. Dinamik bir değişkenin adını almanız durumunda herhangi bir çözüm daha güvenli midir? Her durumda, javascript'in kendisi gerçek güvenlik için değildir (sunucu tarafı açık bir şekilde ana savunmadır). Eğer ilgileniyorsanız, ben değiştirmek isterim eval benim kullanım örneği: stackoverflow.com/a/48294208
Düzenli Joe

2

Kullanıcı tarafından gönderilen kodu yürütüyorsanız olası güvenlik sorunlarının yanı sıra, çoğu zaman kodu her yürütüldüğünde yeniden ayrıştırmayı içermeyen daha iyi bir yol vardır. Anonim işlevler veya nesne özellikleri, eval'ün çoğu kullanımının yerini alabilir ve çok daha güvenli ve daha hızlıdır.


2

Bu, yeni nesil tarayıcıların bir JavaScript derleyicisinin bazı lezzetleri ile ortaya çıkması nedeniyle daha fazla sorun olabilir. Eval ile yürütülen kod, JavaScript'inizin geri kalanını bu yeni tarayıcılara karşı iyi performans göstermeyebilir. Birisi profilleme yapmalı.


2

Bu, eval ve nasıl bir kötülük olmadığı hakkında konuşan iyi makalelerden biridir: http://www.nczonline.net/blog/2013/06/25/eval-isnt-evil-just-misunderstood/

Ben bitirmek ve her yerde eval () kullanmaya başlamak gerektiğini söylemiyorum. Aslında, eval () işlevini çalıştırmak için çok az iyi kullanım durumu vardır. Kod açıklığı, hata ayıklama ve kesinlikle göz ardı edilmemesi gereken performansla ilgili endişeler vardır. Ancak eval () 'in mantıklı olduğu bir vakanız olduğunda kullanmaktan korkmamalısınız. Önce kullanmamaya çalışın, ancak eval () uygun şekilde kullanıldığında kodunuzun daha kırılgan veya daha az güvenli olduğunu düşünmesine izin vermeyin.


2

eval () çok güçlüdür ve bir JS ifadesini yürütmek veya bir ifadeyi değerlendirmek için kullanılabilir. Ancak soru eval () kullanımı ile ilgili değildir, sadece eval () ile çalıştırdığınız dizenin kötü niyetli bir taraftan nasıl etkilendiğini söyleyelim. Sonunda kötü amaçlı kod çalıştırıyorsunuz. Güç ile büyük sorumluluk gelir. Bu yüzden akıllıca kullanın. Bu eval () işlevi ile çok ilgili değildir, ancak bu makalede oldukça iyi bilgiler vardır: http://blogs.popart.com/2009/07/javascript-injection-attacks/ eval () ile ilgili temel bilgileri arıyorsanız buraya bakın: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval


2

JavaScript Engine, derleme aşamasında gerçekleştirdiği bir dizi performans optimizasyonuna sahiptir. Bunlardan bazıları, kodu lex olarak temel olarak statik olarak analiz edebilmek ve tüm değişken ve işlev bildirimlerinin nerede olduğunu önceden belirlemek için kaynar, böylece yürütme sırasında tanımlayıcıları çözmek daha az çaba gerektirir.

Ancak Motor kodda bir eval (..) bulursa, esas olarak tanımlayıcı konumunun tüm farkındalığının geçersiz olabileceğini varsaymalıdır, çünkü lexing zamanında eval'e hangi kodu geçirebileceğinizi tam olarak bilemez (..) yeni bir sözlüksel kapsam oluşturmak için sözcüksel kapsamı veya geçebileceğiniz nesnenin içeriğini değiştirmek için.

Başka bir deyişle, kötümser anlamda, eval (..) mevcutsa yapacağınız optimizasyonların çoğu anlamsızdır, bu yüzden optimizasyonları hiç yapmaz.

Bu her şeyi açıklıyor.

Referans :

https://github.com/getify/You-Dont-Know-JS/blob/master/scope%20&%20closures/ch2.md#eval

https://github.com/getify/You-Dont-Know-JS/blob/master/scope%20&%20closures/ch2.md#performance


Hiçbir javascript motoru kodda% 100 garanti ile bulamaz ve değerlendiremez. Bu nedenle, her zaman buna hazır olmalıdır.
Jack Giffin

2

Bu her zaman kötü bir fikir değildir. Örneğin, kod oluşturma. Son zamanlarda, sanal dom ve gidon arasındaki boşluğu köprüleyen Hyperbars adlı bir kütüphane yazdım . Bunu, bir gidon şablonunu ayrıştırarak ve daha sonra sanal dom tarafından kullanılan hiperscript'e dönüştürerek yapar . Hiper metin önce bir dize olarak oluşturulur ve döndürülmeden önce çalıştırılabilir koda dönüştürülür. Bu özel durumda kötülüğün tam tersini buldum .eval()eval()

Temel olarak

<div>
    {{#each names}}
        <span>{{this}}</span>
    {{/each}}
</div>

Buna

(function (state) {
    var Runtime = Hyperbars.Runtime;
    var context = state;
    return h('div', {}, [Runtime.each(context['names'], context, function (context, parent, options) {
        return [h('span', {}, [options['@index'], context])]
    })])
}.bind({}))

eval()Oluşturulan dizeyi yalnızca bir kez yorumlamanız ve ardından yürütülebilir çıktıyı birçok kez yeniden kullanmanız gerektiğinden, böyle bir durumda performans bir sorun değildir.

Burada merak ediyorsanız kod oluşturma işleminin nasıl gerçekleştirildiğini görebilirsiniz .


2

eval()Tarayıcılarda çalıştırılan javascript'te kullanmanın gerçekten önemli olmadığını söyleyecek kadar ileri giderdim . * (İhtar)

Tüm modern tarayıcılarda yine de keyfi javascript çalıştırabileceğiniz bir geliştirici konsolu vardır ve herhangi bir yarı akıllı geliştirici JS kaynağınıza bakabilir ve istedikleri şeyi yapmak için ihtiyaç duydukları her şeyi geliştirici konsoluna koyabilir.

* Sunucu uç noktalarınız kullanıcı tarafından sağlanan değerlerin doğru doğrulanması ve dezenfeksiyonu olduğu sürece, istemci tarafı javascriptinizde neyin ayrıştırıldığı ve değerlendirildiği önemli değildir.

eval()Ancak PHP'de kullanmanın uygun olup olmadığını sormak isterseniz , eval ifadenize iletilebilecek herhangi bir değeri beyaz listeye eklemediğiniz sürece cevap NO'dur .


sadece bir dev konsolu değil, aynı zamanda eski IE tarayıcılarında ve mobil cihazlarda olduğu gibi, sayfada kendi dev konsolunuzu oluşturmak için url çubuğuna kod yazabilirsiniz.
Dmitry

1

Şimdiye kadar söylenen hiçbir şeyi reddetmeye çalışmayacağım, ancak eval () 'in (bildiğim kadarıyla) başka bir şekilde yapılamayacağını bu şekilde sunacağım. Muhtemelen bunu kodlamanın başka yolları ve muhtemelen onu optimize etmenin yolları vardır, ancak bu, uzun süre ve herhangi bir çan ve ıslık olmadan, başka alternatifleri olmayan bir eval kullanımını göstermek için yapılır. Yani: dinamik olarak (veya daha doğru) programla oluşturulan nesne adları (değerlerin aksine).

//Place this in a common/global JS lib:
var NS = function(namespace){
    var namespaceParts = String(namespace).split(".");
    var namespaceToTest = "";
    for(var i = 0; i < namespaceParts.length; i++){
        if(i === 0){
            namespaceToTest = namespaceParts[i];
        }
        else{
            namespaceToTest = namespaceToTest + "." + namespaceParts[i];
        }

        if(eval('typeof ' + namespaceToTest) === "undefined"){
            eval(namespaceToTest + ' = {}');
        }
    }
    return eval(namespace);
}


//Then, use this in your class definition libs:
NS('Root.Namespace').Class = function(settings){
  //Class constructor code here
}
//some generic method:
Root.Namespace.Class.prototype.Method = function(args){
    //Code goes here
    //this.MyOtherMethod("foo"));  // => "foo"
    return true;
}


//Then, in your applications, use this to instantiate an instance of your class:
var anInstanceOfClass = new Root.Namespace.Class(settings);

EDIT: Bu arada, (şimdiye kadar işaret edilen tüm güvenlik nedenleriyle) size nesne adlarını kullanıcı girişine dayandırmanızı önermem. Yine de bunu yapmak için iyi bir neden düşünemiyorum. Yine de, bunun iyi bir fikir olmayacağına dikkat çekeceğimi düşündüm :)


3
Bu ile yapılabilir namespaceToTest[namespaceParts[i]], burada değerlendirme gerek yok, bu yüzden if(typeof namespaceToTest[namespaceParts[i]] === 'undefined') { namespaceToTest[namespaceParts[i]] = {};tek farkelse namespaceToTest = namespaceToTest[namespaceParts[i]];
user2144406 14:06

1

Çöp toplama

Tarayıcıların çöp toplama işlemi, değerlendirilen kodun bellekten kaldırılıp kaldırılamayacağı konusunda bir fikre sahip olmadığından, sayfa yeniden yüklenene kadar depolanmış olarak kalır. Kullanıcılarınız kısa süre içinde sayfanızda ise çok kötü değil, ancak web uygulamaları için bir sorun olabilir.

İşte sorunu gösterecek bir komut dosyası

https://jsfiddle.net/CynderRnAsh/qux1osnw/

document.getElementById("evalLeak").onclick = (e) => {
  for(let x = 0; x < 100; x++) {
    eval(x.toString());
  }
};

Yukarıdaki kod kadar basit bir şey, uygulama ölünceye kadar az miktarda belleğin depolanmasına neden olur. Değerlendirilen komut dosyası dev bir işlev olduğunda ve aralıkta çağrıldığında bu daha kötüdür.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.