Mengapa menggunakan fungsi JavaScript JavaScript ide yang buruk?

534

Fungsi eval adalah cara yang kuat dan mudah untuk menghasilkan kode secara dinamis, jadi apa peringatannya?

Brian Singh
sumber
92
Don't be eval () oleh Simon Willison - 24ways.org/2005/dont-be-eval
Brian Singh
5
Sebagaimana diuraikan dalam moduscreate.com/javascript-performance-tips-tricks - (Fungsi baru (str)) () lebih performan daripada eval (str). Just my 2 cents :)
Grgur
3
rupanya fcuntion baru (a) 67% lebih lambat dari eval (a) di chrome
apa itu sleep
bagi saya fungsi baru (a) adalah 80% lebih lambat chrome terbaru di osx
john Smith
3
Saya menambahkan fungsi statis, hanya untuk membandingkan kinerjanya. jsperf.com/eval-vs-new-function/2
Nepoxx

Jawaban:

386
  1. Penggunaan eval yang tidak tepat akan membuka kode Anda untuk serangan injeksi

  2. Debugging bisa lebih menantang (tidak ada nomor baris, dll.)

  3. kode eval'd mengeksekusi lebih lambat (tidak ada kesempatan untuk mengkompilasi / cache kode eval'd)

Sunting: Seperti yang ditunjukkan oleh @Jeff Walden dalam komentar, # 3 kurang benar hari ini dari pada 2008. Namun, sementara beberapa caching skrip yang dikompilasi dapat terjadi, ini hanya akan terbatas pada skrip yang dievaluasi berulang tanpa modifikasi. Skenario yang lebih mungkin adalah Anda mengevaluasi skrip yang telah mengalami sedikit modifikasi setiap kali dan karenanya tidak dapat di-cache. Anggap saja beberapa kode dijalankan lebih lambat.

Prestaul
sumber
2
@JeffWalden, komentar bagus. Saya telah memperbarui posting saya meskipun saya menyadari sudah setahun sejak Anda memposting. Xnzo72, jika Anda memenuhi syarat komentar Anda (seperti yang dilakukan Jeff) maka saya mungkin bisa setuju dengan Anda. Jeff menunjukkan kunci: "eval dari string yang sama beberapa kali dapat menghindari overhead parse". Karena itu, Anda salah; # 3 berlaku untuk banyak skenario.
Prestaul
7
@ Prestaul: Karena penyerang seharusnya hanya menggunakan alat pengembang apa pun untuk mengubah JavaScript di klien, mengapa Anda mengatakan Eval () membuka kode Anda untuk menyuntikkan serangan? Belum dibuka? (Saya berbicara tentang JavaScript klien)
Eduardo Molteni
60
@EduardoMolteni, kami tidak peduli (dan memang tidak bisa mencegah) pengguna mengeksekusi js di browser mereka sendiri. Serangan yang kami coba hindari adalah ketika nilai yang diberikan pengguna disimpan, kemudian ditempatkan ke dalam javascript dan dievaluasi. Misalnya, saya dapat mengatur nama pengguna saya menjadi: badHackerGuy'); doMaliciousThings();dan jika Anda mengambil nama pengguna saya, menggabungkannya menjadi beberapa skrip dan mengevalasinya di browser orang lain maka saya dapat menjalankan javascript apa pun yang saya inginkan di mesin mereka (misalnya memaksa mereka untuk memberi +1 pada posting saya, memposting data mereka ke server saya, dll.)
Prestaul
3
Secara umum, # 1 berlaku untuk cukup banyak, jika tidak sebagian besar panggilan fungsi. eval () tidak boleh dipilih dan dihindari oleh programmer yang berpengalaman, hanya karena programmer yang tidak berpengalaman menyalahgunakannya. Namun, programmer berpengalaman sering memiliki arsitektur yang lebih baik dalam kode mereka, dan eval () jarang diperlukan atau bahkan dipikirkan karena arsitektur yang lebih baik ini.
frodeborli
4
@TamilVendhan Tentu Anda bisa meletakkan breakpoints. Anda dapat mengakses file virtual yang dibuat oleh Chrome untuk kode berkode Anda dengan menambahkan debugger;pernyataan ke kode sumber Anda. Ini akan menghentikan eksekusi program Anda pada baris itu. Kemudian setelah itu Anda dapat menambahkan debug breakpoint seperti itu hanya file JS lainnya.
Sid
346

eval tidak selalu jahat. Ada saat-saat di mana itu sangat tepat.

Namun, eval saat ini dan secara historis banyak digunakan oleh orang-orang yang tidak tahu apa yang mereka lakukan. Itu termasuk orang yang menulis tutorial JavaScript, sayangnya, dan dalam beberapa kasus ini memang dapat memiliki konsekuensi keamanan - atau, lebih sering, bug sederhana. Jadi semakin banyak yang bisa kita lakukan untuk melemparkan tanda tanya di atas eval, semakin baik. Setiap kali Anda menggunakan eval, Anda perlu melakukan kewarasan-periksa apa yang Anda lakukan, karena kemungkinan besar Anda bisa melakukannya dengan cara yang lebih baik, lebih aman, lebih bersih.

Untuk memberikan contoh yang terlalu umum, untuk mengatur warna elemen dengan id yang disimpan dalam variabel 'kentang':

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

Jika penulis dari jenis kode di atas memiliki petunjuk tentang dasar-dasar cara kerja objek JavaScript, mereka akan menyadari bahwa tanda kurung siku dapat digunakan alih-alih nama-huruf literal, meniadakan perlunya eval:

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

... yang jauh lebih mudah dibaca dan juga kurang berpotensi buggy.

(Tapi kemudian, seseorang yang benar-benar tahu apa yang mereka lakukan akan berkata:

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

yang lebih dapat diandalkan daripada trik lama cerdik mengakses elemen DOM langsung dari objek dokumen.)

bobince
sumber
82
Hmm, kira saya beruntung saat pertama kali belajar JavaScript. Saya selalu menggunakan "document.getElementById" untuk mengakses DOM; ironisnya, saya hanya melakukannya pada saat itu karena saya tidak memiliki petunjuk bagaimana benda-benda bekerja di JavaScript ;-)
Mike Spross
5
setuju. Kadang eval ok misalnya untuk respons JSON dari layanan web
schoetbi
40
@ schoetbi: Tidakkah seharusnya Anda menggunakan JSON.parse()bukan eval()untuk JSON?
nyuszika7h
4
@bobince code.google.com/p/json-sans-eval berfungsi di semua browser, demikian juga github.com/douglascrockford/JSON-js . Json2.js Doug Crockford memang menggunakan eval secara internal, tetapi dengan cek. Selain itu, ini kompatibel dengan forward dengan dukungan browser bawaan untuk JSON.
Martijn
8
@bobince Ada sesuatu yang disebut pendeteksian fitur dan polyfill untuk menangani pustaka JSON yang hilang dan hal-hal lain (lihat modernizr.com )
MauganRa
37

Saya percaya itu karena dapat menjalankan fungsi JavaScript apa pun dari string. Menggunakannya memudahkan orang untuk menyuntikkan kode jahat ke dalam aplikasi.

kemiller2002
sumber
5
Apa alternatifnya?
modern
5
Sungguh alternatifnya adalah hanya menulis kode yang tidak memerlukannya. Crockford menjelaskan tentang hal ini, dan jika Anda perlu menggunakannya, ia cukup banyak mengatakan bahwa ini adalah cacat desain program dan perlu dikerjakan ulang. Sebenarnya, saya setuju dengannya juga. JS untuk semua kekurangannya sangat fleksibel, dan memungkinkan banyak ruang untuk membuatnya fleksibel.
kemiller2002
3
Tidak benar, sebagian besar kerangka kerja memiliki metode untuk mem-parse JSON, dan jika Anda tidak menggunakan kerangka kerja, Anda bisa menggunakan JSON.parse (). Sebagian besar browser mendukungnya, dan jika Anda benar-benar dalam keadaan darurat, Anda bisa menulis parser untuk JSON dengan mudah.
kemiller2002
6
Saya tidak membeli argumen ini, karena sudah mudah untuk menyuntikkan kode jahat ke dalam aplikasi Javascript. Kami memiliki konsol peramban, ekstensi skrip, dll ... Setiap bagian dari kode yang dikirim ke klien adalah opsional untuk dieksekusi oleh klien.
user2867288
6
Intinya adalah lebih mudah bagi saya untuk menyuntikkan kode ke browser Anda. Katakanlah Anda menggunakan eval pada string kueri. Jika saya menipu Anda untuk mengklik tautan yang masuk ke situs itu dengan string kueri saya terlampir, sekarang saya telah mengeksekusi kode saya di mesin Anda dengan izin penuh dari browser. Saya ingin memasukkan semua yang Anda ketik di situs itu dan memasukkannya ke saya? Selesai dan tidak ada cara untuk menghentikan saya karena ketika eval dijalankan, browser memberikannya otoritas tertinggi.
kemiller2002
27

Dua poin muncul dalam pikiran:

  1. Keamanan (tetapi selama Anda menghasilkan string untuk dievaluasi sendiri, ini mungkin bukan masalah)

  2. Kinerja: sampai kode yang dieksekusi tidak diketahui, tidak dapat dioptimalkan. (tentang javascript dan kinerja, tentu saja presentasi Steve Yegge )

xtofl
sumber
9
Mengapa keamanan menjadi masalah jika klien tetap dapat melakukan dengan kode apa pun yang dia inginkan? Greasemonkey?
Paul Brewczynski
2
@PaulBrewczynski, masalah keamanan muncul ketika pengguna A menyimpan bagian kode yang akan digunakan evaldan kemudian, sepotong kecil kode itu berjalan di browser B pengguna
Felipe Pereira
21

Melewati input pengguna ke eval () adalah risiko keamanan, tetapi juga setiap permintaan eval () menciptakan instance baru dari penerjemah JavaScript. Ini bisa menjadi sumber daya babi.

Andrew Hedges
sumber
27
Dalam 3+ tahun sejak saya menjawab ini, pemahaman saya tentang apa yang terjadi, katakanlah, semakin dalam. Apa yang sebenarnya terjadi adalah konteks eksekusi baru dibuat. Lihat dmitrysoshnikov.com/ecmascript/chapter-1-execution-contexts
Andrew Hedges
20

Ini umumnya hanya masalah jika Anda memberikan input pengguna.

Mark Biek
sumber
16

Terutama, jauh lebih sulit untuk mempertahankan dan men-debug. Itu seperti goto. Anda dapat menggunakannya, tetapi itu membuat lebih sulit untuk menemukan masalah dan lebih sulit pada orang-orang yang mungkin perlu melakukan perubahan nanti.

Brian
sumber
Eval dapat digunakan untuk menggantikan fitur pemrograman yang hilang, seperti templat. Saya suka cara generator kompak lebih dari sekadar daftar fungsi pada fungsi.
titik lemah
Selama string tidak berasal dari pengguna, atau terbatas pada browser yang Anda bisa. JavaScript memiliki banyak kekuatan metaprogramming menggunakan hal-hal seperti mengubah prototipe, objek [anggota], Proxy, json.parse, jendela, fungsi dekorator (kata keterangan) di mana newf = dekorator (oldf), fungsi urutan lebih tinggi seperti Array.prototype.map (f) , meneruskan argumen ke fungsi lain, argumen kata kunci melalui {}. Bisakah Anda memberi tahu saya kasus penggunaan di mana Anda tidak bisa melakukan ini bukannya eval?
aoeu256
13

Satu hal yang perlu diingat adalah bahwa Anda sering dapat menggunakan eval () untuk mengeksekusi kode di lingkungan yang dibatasi - situs jejaring sosial yang memblokir fungsi JavaScript tertentu terkadang dapat dibodohi dengan memecahnya dalam blok eval -

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

Jadi, jika Anda ingin menjalankan beberapa kode JavaScript yang mungkin tidak diizinkan ( Myspace , saya melihat Anda ...) maka eval () dapat menjadi trik yang bermanfaat.

Namun, untuk semua alasan yang disebutkan di atas, Anda tidak boleh menggunakannya untuk kode Anda sendiri, di mana Anda memiliki kontrol penuh - itu tidak perlu, dan lebih baik diturunkan ke rak 'hacks JavaScript rumit'.

matt lohkamp
sumber
1
Hanya memperbarui kode di atas .. - ya di sana! - harus dalam tanda kutip karena ini adalah string. eval ('al' + 'er' + 't (' + '"hai!"' + ')');
Mahesh
2
[]["con"+"struc"+"tor"]["con"+"struc"+"tor"]('al' + 'er' + 't(\'' + 'hi there!' + '\')')()
Konrad Borowski
4
Ya, ada situs jejaring sosial yang membatasi peringatan () tetapi mengizinkan eval () ?!
joshden
12

Kecuali Anda membiarkan eval () konten dinamis (melalui cgi atau input), itu sama aman dan solidnya dengan semua JavaScript lainnya di halaman Anda.

Mereka
sumber
Meskipun ini benar - jika konten Anda tidak dinamis, alasan apa yang ada untuk menggunakan eval sama sekali? Anda bisa memasukkan kode ke suatu fungsi dan menyebutnya, sebagai gantinya!
Periata Breatta
Sebagai contoh - untuk mengurai nilai kembali (seperti JSON, string yang ditentukan server, dll.) Yang berasal dari panggilan Ajax.
Thevs
2
Oh begitu. Saya akan menyebutnya dinamis karena klien sebelumnya tidak tahu apa itu, tapi saya mengerti maksud Anda sekarang.
Periata Breatta
7

Seiring dengan sisa jawaban, saya tidak berpikir pernyataan eval dapat memiliki minimalisasi lanjutan.

Paul Mendoza
sumber
6

Ini adalah risiko keamanan yang mungkin terjadi, ia memiliki cakupan eksekusi yang berbeda, dan cukup tidak efisien, karena menciptakan lingkungan scripting yang sama sekali baru untuk pelaksanaan kode. Lihat di sini untuk info lebih lanjut: eval .

Ini cukup berguna, dan digunakan dengan moderasi dapat menambah banyak fungsionalitas yang baik.

Tom
sumber
5

Kecuali Anda 100% yakin bahwa kode yang dievaluasi berasal dari sumber tepercaya (biasanya aplikasi Anda sendiri) maka itu cara yang pasti untuk mengekspos sistem Anda terhadap serangan skrip lintas situs.

John Topley
sumber
1
Hanya jika keamanan sisi server Anda payah. Keamanan sisi klien adalah omong kosong.
doubleOrt
5

Saya tahu diskusi ini sudah lama, tetapi saya sangat suka pendekatan ini oleh Google dan ingin berbagi perasaan itu dengan orang lain;)

Hal lain adalah bahwa semakin baik Anda mendapatkan semakin Anda mencoba untuk memahami dan akhirnya Anda hanya tidak percaya bahwa ada sesuatu yang baik atau buruk hanya karena seseorang berkata begitu :) Ini adalah video yang sangat inspirasional yang membantu saya untuk berpikir lebih banyak sendiri :) PRAKTEK YANG BAIK baik, tetapi jangan menggunakannya dengan sembarangan :)

op1ekun
sumber
1
Iya. Saya telah menemukan, sejauh ini setidaknya di Chrome, kasus penggunaan yang tampaknya lebih efisien. Jalankan RAF yang mengevaluasi string dalam variabel yang diberikan setiap iterasi. Gunakan setInterval untuk mengatur hanya hal-hal yang berorientasi grafis seperti pengaturan transformasi, dll dalam string itu. Saya sudah mencoba banyak pendekatan lain seperti perulangan fungsi dalam array atau menggunakan variabel untuk hanya mengatur transformasi untuk elemen yang diubah, tetapi sejauh ini ini tampaknya paling efisien. Ketika sampai pada animasi, tes bangku paling benar adalah mata Anda.
jdmayfield
5

Itu tidak selalu buruk asalkan Anda tahu apa konteksnya Anda menggunakannya.

Jika aplikasi Anda menggunakan eval()untuk membuat objek dari beberapa JSON yang telah kembali dari XMLHttpRequest ke situs Anda sendiri, dibuat oleh kode sisi server tepercaya Anda, itu mungkin bukan masalah.

Kode JavaScript sisi-klien yang tidak dapat dipercaya tidak dapat melakukan banyak hal. Asalkan hal yang Anda jalankan eval()berasal dari sumber yang masuk akal, Anda baik-baik saja.

MarkR
sumber
3
Bukankah menggunakan eval lebih lambat dari sekadar mengurai JSON?
Brendan Long
@Qix - menjalankan tes itu di browser saya (Chrome 53) menunjukkan eval agak lebih cepat daripada parse .
Periata Breatta
@PeriataBreatta Huh, aneh. Kenapa ya. Pada saat itu saya berkomentar bukan itu masalahnya. Namun, bukan hal yang aneh bagi Chrome untuk mendapatkan peningkatan kinerja aneh di area runtime tertentu dari versi ke versi.
Qix - MONICA DISALAHKAN
Sebuah utas lama di sini, tetapi dari apa yang saya baca - tidak mengklaim saya melacaknya kembali sendiri - JSON. Sebenarnya, eval adalah inputnya di tahap akhir. Jadi dari sisi efisiensi, butuh lebih banyak kerja / waktu. Namun dari segi keamanan, mengapa tidak hanya menguraikan? eval adalah alat yang luar biasa. Gunakan untuk hal-hal yang tidak memiliki cara lain. Untuk melewati fungsi melalui JSON, ada cara untuk melakukannya tanpa eval. Parameter kedua di JSON.stringify memungkinkan Anda melakukan panggilan balik untuk dijalankan yang dapat Anda periksa melalui typeof jika itu sebuah fungsi. Kemudian dapatkan fungsi .toString (). Ada beberapa artikel bagus tentang ini jika Anda mencari.
jdmayfield
4

Ini sangat mengurangi tingkat kepercayaan Anda tentang keamanan.

David Plumpton
sumber
4

Jika Anda ingin pengguna memasukkan beberapa fungsi logis dan mengevaluasi DAN ATAU maka fungsi JavaScript JavaScript sempurna. Saya dapat menerima dua string dan eval(uate) string1 === string2, dll.

Ian
sumber
Anda juga dapat menggunakan Function () {}, tetapi hati-hati saat menggunakannya di server kecuali Anda ingin pengguna mengambil alih server hahahah.
aoeu256
3

Jika Anda melihat penggunaan eval () dalam kode Anda, ingat mantra "eval () adalah jahat."

Fungsi ini mengambil string arbitrer dan menjalankannya sebagai kode JavaScript. Ketika kode tersebut diketahui sebelumnya (tidak ditentukan saat runtime), tidak ada alasan untuk menggunakan eval (). Jika kode dihasilkan secara dinamis saat runtime, sering kali ada cara yang lebih baik untuk mencapai tujuan tanpa eval (). Misalnya, hanya menggunakan notasi braket persegi untuk mengakses properti dinamis lebih baik dan sederhana:

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

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

Penggunaan eval()juga memiliki implikasi keamanan, karena Anda mungkin menjalankan kode (misalnya berasal dari jaringan) yang telah dirusak. Ini adalah antipattern yang umum ketika berhadapan dengan respons JSON dari permintaan Ajax. Dalam kasus tersebut, lebih baik menggunakan metode bawaan browser untuk mem-parse respons JSON untuk memastikan itu aman dan valid. Untuk peramban yang tidak mendukungJSON.parse() secara asli, Anda dapat menggunakan perpustakaan dari JSON.org.

Ini juga penting untuk diingat bahwa string yang lewat untuk setInterval(), setTimeout(), dan Function()konstruktor adalah, untuk sebagian besar, mirip dengan menggunakan eval()dan karena itu harus dihindari.

Di balik layar, JavaScript masih harus mengevaluasi dan mengeksekusi string yang Anda berikan sebagai kode pemrograman:

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

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

Menggunakan Function () constructor baru mirip dengan eval () dan harus didekati dengan hati-hati. Ini bisa menjadi konstruksi yang kuat tetapi sering disalahgunakan. Jika Anda benar-benar harus menggunakaneval() , Anda dapat mempertimbangkan menggunakan Function () baru sebagai gantinya.

Ada sedikit manfaat potensial karena kode yang dievaluasi dalam Function () baru akan berjalan dalam lingkup fungsi lokal, sehingga variabel apa pun yang didefinisikan dengan var dalam kode yang dievaluasi tidak akan menjadi global secara otomatis.

Cara lain untuk mencegah global otomatis adalah dengan membungkus eval()panggilan menjadi fungsi langsung.

12345678
sumber
Bisakah Anda menyarankan bagaimana saya bisa mengevaluasi nama variabel dinamis fungsi-lokal tanpa eval? Fungsi Eval (dan yang serupa) adalah pilihan terakhir dalam sebagian besar bahasa yang mengandungnya, tetapi kadang-kadang diperlukan. Dalam hal mendapatkan nama variabel dinamis, apakah ada solusi yang lebih aman? Bagaimanapun, javascript itu sendiri bukan untuk keamanan nyata (sisi server jelas merupakan pertahanan utama). Jika Anda tertarik, inilah contoh penggunaan saya tentang eval, yang ingin saya ubah: stackoverflow.com/a/48294208
Regular Joe
2

Selain kemungkinan masalah keamanan jika Anda mengeksekusi kode yang dikirimkan pengguna, sebagian besar waktu ada cara yang lebih baik yang tidak melibatkan penguraian ulang kode setiap kali dieksekusi. Fungsi anonim atau properti objek dapat menggantikan sebagian besar penggunaan eval dan jauh lebih aman dan lebih cepat.

Matthew Crumley
sumber
2

Ini mungkin menjadi masalah karena generasi browser berikutnya hadir dengan rasa kompiler JavaScript. Kode yang dieksekusi melalui Eval mungkin tidak berkinerja sebaik JavaScript Anda melawan browser yang lebih baru ini. Seseorang harus melakukan profiling.

Brian
sumber
2

Ini adalah salah satu artikel bagus yang membahas eval dan bagaimana ini bukan kejahatan: http://www.nczonline.net/blog/2013/06/25/eval-isnt-evil-just-misunderstood/

Saya tidak mengatakan Anda harus kehabisan dan mulai menggunakan eval () di mana-mana. Bahkan, ada sangat sedikit kasus penggunaan yang baik untuk menjalankan eval () sama sekali. Jelas ada kekhawatiran dengan kejelasan kode, kemampuan debug, dan tentu saja kinerja yang tidak boleh diabaikan. Tetapi Anda tidak perlu takut untuk menggunakannya ketika Anda memiliki kasus di mana eval () masuk akal. Cobalah untuk tidak menggunakannya terlebih dahulu, tetapi jangan biarkan orang lain membuat Anda berpikir kode Anda lebih rapuh atau kurang aman ketika eval () digunakan dengan tepat.

Amr Elgarhy
sumber
2

eval () sangat kuat dan dapat digunakan untuk mengeksekusi pernyataan JS atau mengevaluasi ekspresi. Tetapi pertanyaannya bukan tentang penggunaan eval () tetapi katakan saja bagaimana string yang Anda jalankan dengan eval () dipengaruhi oleh pihak jahat. Pada akhirnya Anda akan menjalankan kode jahat. Dengan kekuatan muncul tanggung jawab besar. Jadi gunakan dengan bijak Anda menggunakannya. Ini tidak terkait banyak dengan fungsi eval () tetapi artikel ini memiliki informasi yang cukup bagus: http://blogs.popart.com/2009/07/javascript-injection-attacks/ Jika Anda mencari dasar-dasar eval () lihat di sini: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval

Phi
sumber
2

Mesin JavaScript memiliki sejumlah optimasi kinerja yang dilakukan selama fase kompilasi. Beberapa di antaranya bermuara pada dasarnya dapat menganalisis kode secara statis seperti lexes, dan menentukan di mana semua variabel dan deklarasi fungsi berada, sehingga dibutuhkan sedikit usaha untuk menyelesaikan pengidentifikasi selama eksekusi.

Tetapi jika Mesin menemukan eval (..) dalam kode, itu pada dasarnya harus mengasumsikan bahwa semua kesadarannya tentang lokasi pengidentifikasi mungkin tidak valid, karena ia tidak dapat mengetahui pada waktu lexing kode apa yang mungkin Anda lewati untuk eval (..) untuk memodifikasi lingkup leksikal, atau konten objek yang dapat Anda gunakan untuk membuat lingkup leksikal baru untuk dikonsultasikan.

Dengan kata lain, dalam pengertian pesimistis, sebagian besar optimisasi yang dibuatnya tidak ada gunanya jika eval (..) ada, jadi sama sekali tidak melakukan optimasi sama sekali.

Ini menjelaskan semuanya.

Referensi:

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

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

hkasera
sumber
Tidak ada mesin javascript yang tidak dapat menemukan dan mengevaluasi dalam kode dengan jaminan 100%. Karena itu, ia harus siap kapan saja.
Jack Giffin
2

Itu tidak selalu merupakan ide yang buruk. Ambil contoh, pembuatan kode. Baru-baru ini saya menulis sebuah perpustakaan bernama Hyperbars yang menjembatani kesenjangan antara virtual-dom dan setang . Ini dilakukan dengan mem- parsing templat templat dan mengubahnya menjadi hyperscript yang kemudian digunakan oleh virtual-dom. Hyperscript dibuat sebagai string terlebih dahulu dan sebelum mengembalikannya, eval()untuk mengubahnya menjadi kode yang dapat dieksekusi. saya telah menemukaneval() dalam situasi khusus ini kebalikan dari kejahatan.

Pada dasarnya dari

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

Untuk ini

(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({}))

Kinerja eval() bukan masalah dalam situasi seperti ini karena Anda hanya perlu menafsirkan string yang dihasilkan sekali dan kemudian menggunakan kembali hasil yang dapat dieksekusi berkali-kali.

Anda dapat melihat bagaimana pembuatan kode tercapai jika Anda penasaran di sini .

Wiki
sumber
2

Saya akan mengatakan bahwa tidak masalah jika Anda menggunakan eval()javascript yang dijalankan di browser. * (Peringatan)

Semua browser modern memiliki konsol pengembang tempat Anda dapat menjalankan javascript sewenang-wenang dan pengembang semi-cerdas dapat melihat sumber JS Anda dan memasukkan bit apa pun yang mereka perlukan ke konsol dev untuk melakukan apa yang mereka inginkan.

* Selama titik akhir server Anda memiliki validasi & sanitasi yang benar dari nilai yang diberikan pengguna, tidak masalah apa yang diuraikan dan dievaluasi di javascript sisi klien Anda.

Jika Anda bertanya apakah itu cocok untuk digunakan eval()dalam PHP, jawabannya adalah TIDAK , kecuali jika Anda memasukkan daftar putih nilai apa pun yang dapat diteruskan ke pernyataan eval Anda.

Adam Copley
sumber
tidak hanya ada konsol dev, Anda juga dapat mengetikkan javascript: kode di url bar untuk membangun konsol dev Anda sendiri di halaman jika tidak ada, seperti halnya pada browser IE lama dan perangkat seluler.
Dmitry
1

Saya tidak akan mencoba untuk menyangkal apa pun yang dikatakan sebelumnya, tetapi saya akan menawarkan penggunaan eval ini () yang (sejauh yang saya tahu) tidak dapat dilakukan dengan cara lain. Mungkin ada cara lain untuk kode ini, dan mungkin cara untuk mengoptimalkannya, tetapi ini dilakukan dengan tangan dan tanpa bel dan peluit demi kejelasan untuk menggambarkan penggunaan eval yang benar-benar tidak memiliki alternatif lain. Yaitu: nama objek yang dibuat secara dinamis (atau lebih akurat) secara terprogram (sebagai lawan dari nilai).

//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: omong-omong, saya tidak akan menyarankan (untuk semua alasan keamanan menunjukkan sebelumnya) bahwa Anda mendasarkan nama objek Anda pada input pengguna. Saya tidak bisa membayangkan alasan bagus Anda ingin melakukan itu. Tetap saja, kupikir aku akan menunjukkan bahwa itu bukan ide yang bagus :)

Carnix
sumber
3
ini bisa dilakukan dengan namespaceToTest[namespaceParts[i]], tidak perlu untuk eval di sini, jadi satu if(typeof namespaceToTest[namespaceParts[i]] === 'undefined') { namespaceToTest[namespaceParts[i]] = {};-satunya perbedaan untukelse namespaceToTest = namespaceToTest[namespaceParts[i]];
user2144406
1

Pengumpulan sampah

Pengumpulan sampah browser tidak tahu apakah kode yang dievaluasi dapat dihapus dari memori sehingga hanya menyimpannya hingga halaman dimuat ulang. Tidak terlalu buruk jika pengguna Anda tidak lama berada di halaman Anda, tetapi ini bisa menjadi masalah bagi webapp.

Berikut ini skrip untuk menunjukkan masalahnya

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

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

Sesuatu yang sederhana seperti kode di atas menyebabkan sejumlah kecil memori disimpan hingga aplikasi mati. Ini lebih buruk ketika skrip evaled adalah fungsi raksasa, dan disebut interval.

JD
sumber