जावास्क्रिप्ट eval फ़ंक्शन का उपयोग एक बुरा विचार क्यों है?


534

निष्कासन फ़ंक्शन कोड को गतिशील रूप से उत्पन्न करने के लिए एक शक्तिशाली और आसान तरीका है, इसलिए कैवेट क्या हैं?


92
साइमन विलिसन द्वारा eval () मत बनो - 24ways.org/2005/dont-be-eval
ब्रायन सिंह

5
जैसा कि moduscreate.com/javascript-performance-tips-tricks - (new Function (str))) () में eval (str) की तुलना में अधिक परफॉर्म किया गया है । बस मेरे 2 सेंट :)
ग्रगुर

3
जाहिरा तौर पर नई fcuntion (ए) क्रोम पर eval (ए) की तुलना में 67% धीमी है
नींद

मेरे लिए नए कार्य (ए) ओक्स पर 80% धीमे नवीनतम क्रोम हैं
जॉन स्मिथ

3
मैंने केवल प्रदर्शन की तुलना करने के लिए एक स्थिर फ़ंक्शन जोड़ा। jsperf.com/eval-vs-new-function/2
नेपॉक्सएक्स

जवाबों:


386
  1. का अनुचित प्रयोग eval इंजेक्शन हमलों के लिए अपने कोड को खोलता है

  2. डिबगिंग अधिक चुनौतीपूर्ण हो सकती है (कोई पंक्ति संख्या आदि नहीं)

  3. eval'd कोड धीमी गति से क्रियान्वित होता है (कोड संकलन / कैश करने का कोई अवसर नहीं)

संपादित करें: जैसा कि @ जेफ वाल्डेन टिप्पणी में बताते हैं, # 3 आज की तुलना में कम सच है जैसा कि 2008 में था। हालांकि, संकलित लिपियों के कुछ कैशिंग हो सकते हैं यह केवल उन लिपियों तक सीमित होगा जो बिना किसी संशोधन के दोहराए गए हैं। अधिक संभावना परिदृश्य यह है कि आप ऐसी स्क्रिप्ट्स का उपयोग कर रहे हैं, जो हर बार मामूली संशोधन से गुजरती हैं और जैसे कि कैश नहीं किया जा सकता है। मान लीजिए कि कुछ स्पष्ट कोड अधिक धीरे-धीरे निष्पादित होते हैं।


2
@JeffWalden, शानदार टिप्पणी। मैंने अपनी पोस्ट अपडेट कर दी है, हालांकि मुझे लगता है कि आपके पोस्ट किए हुए एक साल हो गया है। Xnzo72, अगर आपने अपनी टिप्पणी कुछ हद तक योग्य की है (जैसा कि जेफ ने किया था) तो मैं आपसे सहमत होने में सक्षम हो सकता हूं। जेफ ने बताया कि: "एक ही स्ट्रिंग का कई बार निकलना पार्स ओवरहेड से बच सकता है"। जैसे भी हो, तुम गलत हो; # 3 कई परिदृश्यों के लिए सही है।
प्रेस्टाले

7
@Prestaul: चूंकि माना जाता है कि हमलावर क्लाइंट में जावास्क्रिप्ट को बदलने के लिए जो भी डेवलपर टूल का उपयोग कर सकते हैं, आप क्यों कहते हैं कि एवल () इंजेक्शन हमलों के लिए आपके कोड को खोलता है? पहले से नहीं खोला गया है? (मैं क्लाइंट जावास्क्रिप्ट के बारे में बात कर रहा हूँ)
एडुआर्डो मोल्टेनई

60
@EduardoMolteni, हम परवाह नहीं करते (और वास्तव में अपने उपयोगकर्ताओं में js निष्पादित करने से उपयोगकर्ताओं को रोक नहीं सकते)। हम जिन हमलों से बचने की कोशिश कर रहे हैं, जब उपयोगकर्ता प्रदान किए गए मानों को सहेजते हैं, तो बाद में जावास्क्रिप्ट और eval'd में रखा जाता है। उदाहरण के लिए, मैं अपना उपयोगकर्ता नाम सेट कर सकता हूं: badHackerGuy'); doMaliciousThings();और यदि आप मेरा उपयोगकर्ता नाम लेते हैं, तो इसे किसी स्क्रिप्ट में ले जाएं और इसे अन्य लोगों के ब्राउज़र में निकाल दें, तो मैं अपनी मशीनों पर अपनी इच्छानुसार कोई भी जावास्क्रिप्ट चला सकता हूं (जैसे कि उन्हें मेरे पोस्ट +1 पर मजबूर कर दें,) मेरे सर्वर, आदि के लिए अपने डेटा पोस्ट)
Prestaul

3
सामान्य तौर पर, # 1 बहुत अधिक के लिए सच है, यदि अधिकांश फ़ंक्शन कॉल नहीं करते हैं। eval () को एकल प्रोग्रामर द्वारा नहीं चुना जाना चाहिए और इससे बचा जाना चाहिए, क्योंकि अनुभवहीन प्रोग्रामर इसका दुरुपयोग करते हैं। हालांकि, अनुभवी प्रोग्रामर के पास अक्सर अपने कोड में बेहतर आर्किटेक्चर होता है, और इस बेहतर आर्किटेक्चर के कारण eval () के बारे में शायद ही कभी आवश्यकता होगी या इसके बारे में सोचा भी जा सकता है।
फ्रोडेबोरली

4
@TamilVendhan यकीन है कि आप ब्रेकप्वाइंट लगा सकते हैं। आप debugger;अपने स्रोत कोड में बयान जोड़कर अपने विकसित कोड के लिए क्रोम द्वारा बनाई गई आभासी फ़ाइल तक पहुंच सकते हैं । यह उस लाइन पर आपके प्रोग्राम के निष्पादन को रोक देगा। फिर उसके बाद आप डिबग ब्रेकपॉइंट जोड़ सकते हैं जैसे कि यह एक और जेएस फ़ाइल थी।
सिड

346

eval हमेशा बुराई नहीं है। कई बार यह पूरी तरह से उपयुक्त है।

हालांकि, eval वर्तमान में और ऐतिहासिक रूप से बड़े पैमाने पर लोगों द्वारा उपयोग किया जाता है जो नहीं जानते कि वे क्या कर रहे हैं। इसमें जावास्क्रिप्ट ट्यूटोरियल लिखने वाले लोग शामिल हैं, दुर्भाग्य से, और कुछ मामलों में यह वास्तव में सुरक्षा परिणाम हो सकता है - या, अधिक बार, सरल बग। इसलिए जितना अधिक हम निष्कासन पर एक प्रश्न चिह्न फेंक सकते हैं, उतना बेहतर होगा। जब भी आप eval का उपयोग करते हैं, तो आपको पवित्रता की जांच करने की आवश्यकता होती है कि आप क्या कर रहे हैं, क्योंकि संभावना है कि आप इसे बेहतर, सुरक्षित, स्वच्छ तरीके से कर सकते हैं।

चर-आलू में संग्रहीत आईडी के साथ एक तत्व का रंग सेट करने के लिए, सभी-बहुत-विशिष्ट उदाहरण देने के लिए:

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

यदि ऊपर दिए गए कोड के प्रकार के लेखकों का जावास्क्रिप्ट ऑब्जेक्ट कैसे काम करता है, इसके मूल के बारे में एक सुराग था, तो उन्हें एहसास हुआ कि शाब्दिक डॉट-नामों के बजाय स्क्वायर ब्रैकेट का उपयोग किया जा सकता है, जो eval की आवश्यकता को पूरा करते हैं:

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

... जो पढ़ना आसान है और साथ ही कम संभावित छोटी गाड़ी भी।

(लेकिन फिर, कोई है जो वास्तव में / जानता था कि वे क्या कर रहे थे:

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

जो डॉम तत्वों को डॉक्यूमेंट ऑब्जेक्ट से सीधे एक्सेस करने की पुरानी पुरानी चाल से अधिक विश्वसनीय है।)


82
हम्म, लगता है कि मैं भाग्यशाली था जब मैं पहली बार जावास्क्रिप्ट सीख रहा था। DOM का उपयोग करने के लिए मैंने हमेशा "document.getElementById" का उपयोग किया; विडंबना यह है कि मैंने इसे केवल उस समय किया क्योंकि मेरे पास कोई सुराग नहीं था कि ऑब्जेक्ट्स जावास्क्रिप्ट में कैसे काम करते हैं ;-)
माइक स्पार्क

5
इस बात से सहमत। कई बार webservices से JSON प्रतिक्रियाओं के लिए eval ठीक है जैसे
schoetbi

40
@schoetbi: क्या आपको JSON के JSON.parse()बजाय उपयोग नहीं करना चाहिए eval()?
न्युसिका 7

4
@bobince code.google.com/p/json-sans-eval सभी ब्राउज़रों पर काम करता है, इसलिए github.com/douglascrockford/JSON-js करता है । डौग क्रॉकफोर्ड का json2.js आंतरिक रूप से, लेकिन चेक के साथ eval का उपयोग करता है। इसके अलावा, यह JSON के लिए अंतर्निहित ब्राउज़र समर्थन के साथ आगे-संगत है।
Martijn

8
@bobince लापता JSON पुस्तकालयों और अन्य चीजों को संभालने के लिए फीचर-डिटेक्शन और पॉलीफ़िल्स नाम की कोई चीज़ है ( आधुनिकीकरण
डॉट कॉम

37

मेरा मानना ​​है कि यह इसलिए है क्योंकि यह स्ट्रिंग से किसी भी जावास्क्रिप्ट फ़ंक्शन को निष्पादित कर सकता है। इसका उपयोग करने से लोगों को एप्लिकेशन में दुष्ट कोड इंजेक्ट करना आसान हो जाता है।


5
फिर विकल्प क्या है?
आधुनिक

5
वास्तव में विकल्प सिर्फ लिखना है कि कोड की आवश्यकता नहीं है। क्रॉकफ़ोर्ड इस बारे में लंबाई में चला जाता है, और यदि आपको इसका उपयोग करने की आवश्यकता है, तो वह बहुत ज्यादा कहता है कि इसका प्रोग्राम डिजाइन दोष है और इसे फिर से काम करने की आवश्यकता है। सच में, मैं भी उससे सहमत हूँ। सभी खामियों के लिए जेएस वास्तव में लचीला है, और बहुत सारे कमरे को लचीला बनाने की अनुमति देता है।
kemiller2002

3
सच नहीं है, अधिकांश फ्रेमवर्क में JSON को पार्स करने की एक विधि है, और यदि आप एक फ्रेमवर्क का उपयोग नहीं कर रहे हैं, तो आप JSON.parse () का उपयोग कर सकते हैं। अधिकांश ब्राउज़र इसका समर्थन करते हैं, और यदि आप वास्तव में चुटकी में हैं, तो आप JSON के लिए बहुत आसानी से एक पार्सर लिख सकते हैं।
kemiller2002

6
मैं इस तर्क को नहीं खरीदता, क्योंकि पहले से ही एक जावास्क्रिप्ट कोड में दुष्ट कोड इंजेक्ट करना आसान है। हमारे पास ब्राउज़र कंसोल, स्क्रिप्ट एक्सटेंशन आदि हैं ... क्लाइंट को भेजा गया कोड का हर एक टुकड़ा क्लाइंट को निष्पादित करने के लिए वैकल्पिक है।
user2867288

6
मुद्दा यह है कि आपके ब्राउज़र में कोड इंजेक्ट करना मेरे लिए आसान है। मान लें कि आप क्वेरी स्ट्रिंग पर eval का उपयोग कर रहे हैं। अगर मैं आपको उस लिंक पर क्लिक करने में ट्रिक करता हूं, जो मेरे क्वेरी स्ट्रिंग के साथ उस साइट पर जाती है, तो मैंने अब ब्राउज़र से पूरी अनुमति के साथ आपके मशीन पर अपना कोड निष्पादित कर दिया है। मैं उस साइट पर आपके द्वारा टाइप की गई सभी चीज़ों को कुंजीबद्ध करना चाहता हूँ और मुझे भेजना चाहता हूँ? किया और मुझे रोकने के लिए कोई रास्ता नहीं है क्योंकि जब निष्कासन निष्पादित होता है, तो ब्राउज़र इसे उच्चतम अधिकार देता है।
kemiller2002

27

दो बिंदु दिमाग में आते हैं:

  1. सुरक्षा (लेकिन जब तक आप स्वयं का मूल्यांकन करने के लिए स्ट्रिंग उत्पन्न करते हैं, यह एक गैर-मुद्दा हो सकता है)

  2. प्रदर्शन: जब तक कोड को अंजाम नहीं दिया जाता है, तब तक इसे अनुकूलित नहीं किया जा सकता है। (जावास्क्रिप्ट और प्रदर्शन के बारे में, निश्चित रूप से स्टीव येजे की प्रस्तुति )


9
क्यों सुरक्षा एक मुद्दा है अगर ग्राहक वैसे भी हमारे कोड के साथ कुछ भी कर सकता है / वह चाहता है? तेल बंदर ?
पॉल ब्रुवेस्किनस्की

2
@PaBBrewczynski, सुरक्षा समस्या तब प्रकट होती है जब उपयोगकर्ता A कोड के अपने हिस्से को यूटेट होने के लिए सहेजता है evalऔर फिर, कोड का एक छोटा टुकड़ा उपयोगकर्ता के B ब्राउज़र पर चलता है
फेलिप परेरा

21

Eval () के लिए उपयोगकर्ता इनपुट पास करना एक सुरक्षा जोखिम है, लेकिन eval () का प्रत्येक आह्वान जावास्क्रिप्ट दुभाषिया का एक नया उदाहरण बनाता है। यह एक संसाधन हॉग हो सकता है।


27
3+ वर्षों में जब से मैंने इसका उत्तर दिया है, मेरी समझ में क्या होता है, आइए बताते हैं, गहरा हुआ है। वास्तव में क्या होता है एक नया निष्पादन संदर्भ बनाया जाता है। देखें dmitrysoshnikov.com/ecmascript/chapter-1-execution-contexts
एंड्रयू हेजेज

20

यदि आप eval उपयोगकर्ता इनपुट पास कर रहे हैं तो यह आम तौर पर केवल एक समस्या है।


16

मुख्य रूप से, इसे बनाए रखना और डिबग करना बहुत कठिन है। यह एक तरह है goto। आप इसका उपयोग कर सकते हैं, लेकिन यह समस्याओं को खोजने के लिए कठिन है और उन लोगों पर कठिन है जिन्हें बाद में बदलाव करने की आवश्यकता हो सकती है।


टेम्प्लेट की तरह लापता मेटाप्रोग्रामिंग फीचर्स को बदलने के लिए इवल का उपयोग किया जा सकता है। मुझे कार्यों पर अंतहीन सूची से अधिक कॉम्पैक्ट जनरेटर तरीका पसंद है।
कमजोर

जब तक स्ट्रिंग उपयोगकर्ता से नहीं आती है, या उस ब्राउज़र तक सीमित है जो आप कर सकते हैं। जावास्क्रिप्ट में बहुत सारे मेटाप्रोग्रामिंग पॉवर होते हैं जैसे कि बदलते प्रोटोटाइप, obj [मेंबर], प्रॉक्सी, json.parse, विंडो, डेकोरेटर फ़ंक्शंस (क्रियाविशेषण) जहाँ newf = डेकोरेटर (ओल्डफ़), Array.prototyp.map (f) जैसे उच्च क्रम वाले सामान का उपयोग करना अन्य कार्यों के लिए तर्कों को पास करना, {} के माध्यम से खोजशब्द तर्क। क्या आप मुझे एक उपयोग का मामला बता सकते हैं, जहाँ आप इनका उपयोग नहीं कर सकते हैं?
aoeu256

13

एक बात का ध्यान रखें कि आप अक्सर अन्यथा प्रतिबंधित वातावरण में कोड को निष्पादित करने के लिए eval () का उपयोग कर सकते हैं - विशिष्ट नेटवर्किंग फ़ंक्शंस को ब्लॉक करने वाले सोशल नेटवर्किंग साइट को कभी-कभी एक eval ब्लॉक में तोड़कर मूर्ख बनाया जा सकता है -

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

इसलिए यदि आप कुछ जावास्क्रिप्ट कोड चलाना चाहते हैं, जहां इसे अन्यथा अनुमति नहीं दी जा सकती है ( माइस्पेस , मैं आपको देख रहा हूं ...) तो eval () एक उपयोगी चाल हो सकती है।

हालांकि, ऊपर उल्लिखित सभी कारणों के लिए, आपको इसका उपयोग अपने कोड के लिए नहीं करना चाहिए, जहां आपका पूर्ण नियंत्रण है - यह केवल आवश्यक नहीं है, और 'मुश्किल जावास्क्रिप्ट हैक्स' शेल्फ पर लगाए गए बेहतर-बंद।


1
बस उपरोक्त कोड को अपडेट करना .. - वही -! यह एक स्ट्रिंग के रूप में उद्धरण में होने की आवश्यकता है। eval ('al' + 'er' + 't (' + '"hi there!"' + ')');
महेश

2
[]["con"+"struc"+"tor"]["con"+"struc"+"tor"]('al' + 'er' + 't(\'' + 'hi there!' + '\')')()
कोनराड बोरोस्की

3
Yikes, सोशल नेटवर्किंग साइटें थीं जो अलर्ट () को प्रतिबंधित करती थीं लेकिन eval () की अनुमति देती थीं ?!
जॉशडेन

12

जब तक आप eval () एक गतिशील सामग्री (cgi या इनपुट के माध्यम से) नहीं देते, तब तक यह आपके पृष्ठ के अन्य सभी JavaScript के समान सुरक्षित और ठोस है।


हालांकि यह सच है - यदि आपकी सामग्री गतिशील नहीं है , तो इसके लिए क्या कारण है? आप कोड को किसी फ़ंक्शन में रख सकते हैं और इसके बजाय उसे कॉल कर सकते हैं!
पेरिआटा ब्रेटा

केवल उदाहरण के लिए - रिटर्निंग वैल्यू को पार्स करने के लिए (जेएसएन जैसे, सर्वर परिभाषित स्ट्रिंग्स, आदि) जो कि अजाक्स कॉल से आया था।
thevs

2
ओह मैं समझा। मैं उन गतिशील को बुलाऊंगा क्योंकि ग्राहक समय से पहले नहीं जानते कि वे क्या हैं, लेकिन मैं देख रहा हूं कि अब आपका क्या मतलब है।
पेरिआटा ब्रेट्टा

7

बाकी जवाबों के साथ, मुझे नहीं लगता कि eval स्टेटमेंट में कम से कम एडवांसमेंट हो सकता है।


6

यह एक संभावित सुरक्षा जोखिम है, इसमें निष्पादन की एक अलग गुंजाइश है, और यह काफी अक्षम है, क्योंकि यह कोड के निष्पादन के लिए पूरी तरह से नया स्क्रिप्टिंग वातावरण बनाता है। कुछ और जानकारी के लिए यहाँ देखें: eval

यह काफी उपयोगी है, हालांकि, और मॉडरेशन के साथ इसका उपयोग बहुत अच्छी कार्यक्षमता जोड़ सकता है।


5

जब तक आप 100% सुनिश्चित नहीं हो जाते हैं कि मूल्यांकन किए जा रहे कोड एक विश्वसनीय स्रोत (आमतौर पर आपके स्वयं के अनुप्रयोग) से है तो यह आपके सिस्टम को क्रॉस-साइट स्क्रिप्टिंग हमले को उजागर करने का एक निश्चित तरीका है।


1
केवल अगर आपका सर्वर-साइड सुरक्षा बेकार है। क्लाइंट-साइड सुरक्षा सीधे बकवास है।
डबलऑर्ट

5

मुझे पता है कि यह चर्चा पुरानी है, लेकिन मुझे वास्तव में यह पसंद है में Google के दृष्टिकोण को और उस भावना को दूसरों के साथ साझा करना चाहता हूं;)

दूसरी बात यह है कि आप जितना बेहतर पाते हैं उतना ही आप समझने की कोशिश करते हैं और आखिरकार आप यह नहीं मानते हैं कि कुछ अच्छा या बुरा है क्योंकि किसी ने ऐसा कहा है :) यह एक बहुत ही प्रेरणादायक वीडियो है जिसने मुझे खुद से और अधिक सोचने में मदद की। :) अच्छे प्रभाव अच्छे हैं, लेकिन उन्हें बेकार का उपयोग न करें :)


1
हाँ। मैंने पाया है, अब तक कम से कम क्रोम में, एक उपयोग मामला जो अधिक कुशल लगता है। एक आरएएफ चलाएं जो किसी दिए गए चर में प्रत्येक स्ट्रिंग में एक स्ट्रिंग को विकसित करता है। उस स्ट्रिंग में केवल ट्रांसफ़ॉर्मिंग सेटिंग आदि जैसी ग्राफ़िकल-ओरिएंटेड चीज़ें सेट करने के लिए एक सेटइंटरवल का उपयोग करें। मैंने कई अन्य तरीकों की कोशिश की है जैसे कि एक सरणी में फ़ंक्शन के माध्यम से लूपिंग या परिवर्तनशील तत्वों के लिए केवल परिवर्तन सेट करने के लिए चर का उपयोग करना, लेकिन अभी तक यह सबसे अधिक कुशल लगता है। जब यह एनीमेशन के लिए नीचे आता है, तो ट्रुस्ट बेंच-टेस्ट आपकी आँखें हैं।
jdmayfield

5

यह जरूरी नहीं है कि बुरा आप प्रदान करते हैं कि आप जानते हैं कि आप किस संदर्भ में इसका उपयोग कर रहे हैं।

यदि आपका एप्लिकेशन eval()कुछ JSON से एक ऑब्जेक्ट बनाने के लिए उपयोग कर रहा है जो XMLHttpRequest से आपकी साइट पर वापस आ गया है , जो आपके विश्वसनीय सर्वर-साइड कोड द्वारा बनाया गया है, तो यह संभवतः एक समस्या नहीं है।

अविश्वसनीय ग्राहक पक्ष जावास्क्रिप्ट कोड वैसे भी इतना नहीं कर सकता। बशर्ते आप जिस eval()पर अमल कर रहे हैं, वह एक उचित स्रोत से आया हो, आप ठीक हैं।


3
सिर्फ JSON को पार्स करने की तुलना में eval धीमे का उपयोग नहीं कर रहा है?
ब्रेंडन लॉन्ग

@Qix - अपने ब्राउज़र पर कि परीक्षण चल रहा है (क्रोम 53) से पता चलता है eval के रूप में कुछ हद तक की तुलना में तेजी पार्स
पेरिआटा ब्रेटा

@PeriataBreatta हुह, अजीब। मुझे आश्चर्य है क्योंकि। उस समय मैंने टिप्पणी की थी कि ऐसा नहीं था। हालाँकि, संस्करण से संस्करण तक रनटाइम के कुछ क्षेत्रों में अजीब प्रदर्शन को बढ़ावा देने के लिए क्रोम के लिए यह अनसुना नहीं है।
Qix - मोनासा

यहाँ एक छोटा सा पुराना धागा है, लेकिन जो मैंने पढ़ा है उससे - मैं यह दावा नहीं कर रहा हूँ कि मैंने इसे स्वयं वापस ले लिया है - JSON.parse वास्तव में eval का अंतिम चरण में इनपुट है। तो दक्षता-वार, अधिक काम / समय लेता है। लेकिन सुरक्षा के लिहाज से, सिर्फ पार्स क्यों नहीं? eval एक कमाल का टूल है। इसका इस्तेमाल उन चीजों के लिए करें, जिनका कोई दूसरा तरीका नहीं है। JSON के माध्यम से फ़ंक्शंस पास करने के लिए, इसे eval के बिना करने का एक तरीका है। JSON.stringify में वह दूसरा पैरामीटर आपको एक कॉलबैक चलाने की सुविधा देता है जिसे आप टाइपोफ के माध्यम से जांच सकते हैं यदि यह एक फ़ंक्शन है। फिर फ़ंक्शन .toString () प्राप्त करें। यदि आप खोज करते हैं तो इस पर कुछ अच्छे लेख हैं।
jdmayfield


4

यदि आप चाहते हैं कि उपयोगकर्ता कुछ तार्किक कार्यों का इनपुट करे और AND के लिए मूल्यांकन करे और फिर JavaScript eval फ़ंक्शन सही हो। मैं दो तार और स्वीकार कर सकता हूं eval(uate) string1 === string2, आदि।


आप फ़ंक्शन () {} का भी उपयोग कर सकते हैं, लेकिन सर्वर पर इन का उपयोग करते समय सावधान रहें जब तक कि आप उपयोगकर्ताओं को अपने सर्वर पर नहीं लेना चाहते।
aoeu256

3

यदि आप अपने कोड में eval () का उपयोग करते हैं, तो याद रखें मंत्र "eval () बुराई है।"

यह फ़ंक्शन एक मनमाना स्ट्रिंग लेता है और इसे जावास्क्रिप्ट कोड के रूप में निष्पादित करता है। जब प्रश्न में कोड पहले से जाना जाता है (रनटाइम पर निर्धारित नहीं), तो eval () का उपयोग करने का कोई कारण नहीं है। यदि कोड गतिशील रूप से रनटाइम पर उत्पन्न होता है, तो अक्सर eval () के बिना लक्ष्य प्राप्त करने का एक बेहतर तरीका है। उदाहरण के लिए, गतिशील गुणों तक पहुँचने के लिए चौकोर ब्रैकेट नोटेशन का उपयोग करना बेहतर और सरल है:

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

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

का उपयोग करते हुए eval() भी सुरक्षा निहितार्थ हैं, क्योंकि आप कोड को निष्पादित कर सकते हैं (उदाहरण के लिए नेटवर्क से आने वाला) जो छेड़छाड़ किया गया है। यह एक अजाक्स अनुरोध से JSON प्रतिक्रिया के साथ काम करते समय एक सामान्य एंटीपैटर्न है। उन मामलों में, यह सुनिश्चित करने के लिए कि यह सुरक्षित और वैध है, JSON प्रतिक्रिया को पार्स करने के लिए ब्राउज़रों के अंतर्निहित तरीकों का उपयोग करना बेहतर है। ब्राउज़रों के लिए जो समर्थन नहीं करते हैंJSON.parse() मूल रूप से , आप JSON.org से एक पुस्तकालय का उपयोग कर सकते हैं।

यह भी है कि गुजर तार याद रखना महत्वपूर्ण है setInterval(), setTimeout()औरFunction() निर्माता अधिकांश भाग, उपयोग करने के समान के लिए, है eval()और इसलिए बचा जाना चाहिए।

दृश्यों के पीछे, जावास्क्रिप्ट को अभी भी प्रोग्रामिंग कोड के रूप में आपके द्वारा पारित स्ट्रिंग का मूल्यांकन और निष्पादित करना है:

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

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

नए फ़ंक्शन () कंस्ट्रक्टर का उपयोग करना eval () के समान है और देखभाल के साथ संपर्क किया जाना चाहिए। यह एक शक्तिशाली निर्माण हो सकता है लेकिन अक्सर इसका दुरुपयोग होता है। यदि आप बिल्कुल उपयोग करना चाहिएeval() , तो आप इसके बजाय नए फ़ंक्शन () का उपयोग करने पर विचार कर सकते हैं।

एक छोटा सा संभावित लाभ है क्योंकि नए फ़ंक्शन () में मूल्यांकन किए गए कोड एक स्थानीय फ़ंक्शन दायरे में चल रहे होंगे, इसलिए मूल्यांकन किए जा रहे कोड में वेरिएबल के साथ परिभाषित किसी भी चर स्वचालित रूप से ग्लोबल्स नहीं बन जाएंगे।

स्वचालित ग्लोबल्स को रोकने का एक अन्य तरीका eval()कॉल को तत्काल फ़ंक्शन में लपेटना है ।


क्या आप सुझाव दे सकते हैं कि मैं एक स्थानीय-स्थानीय गतिशील चर नाम का मूल्यांकन कैसे कर सकता हूँ? अधिकांश भाषाओं में एवल (और इसी तरह) फ़ंक्शन अंतिम-रिज़ॉर्ट होते हैं जिनमें उन्हें शामिल किया जाता है, लेकिन कभी-कभी यह आवश्यक होता है। डायनामिक वैरिएबल का नाम प्राप्त करने के मामले में, क्या कोई समाधान अधिक सुरक्षित है? किसी भी मामले में, जावास्क्रिप्ट स्वयं वास्तविक सुरक्षा के लिए नहीं है (सर्वर-साइड स्पष्ट रूप से मुख्य बचाव है)। यदि आप रुचि रखते हैं, तो यहाँ मेरे प्रयोग का मामला है, जिसे मैं बदलना पसंद करूँगा: stackoverflow.com/a/48294208
Regular Joe

2

यदि आप उपयोगकर्ता द्वारा सबमिट किए गए कोड को निष्पादित कर रहे हैं, तो संभव सुरक्षा समस्याओं के अलावा, अधिकांश समय एक बेहतर तरीका है जो कोड को निष्पादित करने पर हर बार फिर से पार्स करना शामिल नहीं करता है। बेनामी फ़ंक्शंस या ऑब्जेक्ट गुण, eval के अधिकांश उपयोगों को बदल सकते हैं और बहुत सुरक्षित और तेज़ होते हैं।


2

यह एक समस्या का और अधिक हो सकता है क्योंकि अगली पीढ़ी के ब्राउज़र जावास्क्रिप्ट संकलक के कुछ स्वाद के साथ सामने आते हैं। एवल के माध्यम से निष्पादित कोड इन नए ब्राउज़रों के खिलाफ आपके जावास्क्रिप्ट के बाकी हिस्सों के साथ-साथ प्रदर्शन नहीं कर सकता है। किसी को कुछ प्रोफाइलिंग करनी चाहिए।


2

यह एक अच्छा लेख है जो eval के बारे में बात कर रहा है और यह कैसे एक बुराई नहीं है: http://www.nczonline.net/blog/2013/06/25/eval-isnt-evil-just-misunderstood/

मैं यह नहीं कह रहा हूं कि आपको बाहर जाना चाहिए और हर जगह eval () का उपयोग करना शुरू कर देना चाहिए। वास्तव में, eval () को चलाने के लिए बहुत कम उपयोग के मामले हैं। कोड स्पष्टता, डिबगैबिलिटी और निश्चित रूप से प्रदर्शन के साथ निश्चित रूप से चिंताएं हैं जिन्हें नजरअंदाज नहीं किया जाना चाहिए। लेकिन आपको इसका उपयोग करने से डरना नहीं चाहिए जब आपके पास एक ऐसा मामला है जहां eval () समझ में आता है। पहले इसका उपयोग न करने की कोशिश करें, लेकिन किसी को भी आपको यह सोचने में डराए नहीं कि जब कोड () का उचित उपयोग किया जाता है तो आपका कोड अधिक नाजुक या कम सुरक्षित होता है।


2

eval () बहुत शक्तिशाली है और इसका उपयोग जेएस स्टेटमेंट को निष्पादित करने या अभिव्यक्ति का मूल्यांकन करने के लिए किया जा सकता है। लेकिन सवाल eval () के उपयोगों के बारे में नहीं है, लेकिन कुछ को यह बताने देता है कि आप eval () के साथ चल रहे स्ट्रिंग को दुर्भावनापूर्ण पार्टी से कैसे प्रभावित करते हैं। अंत में आप दुर्भावनापूर्ण कोड चला रहे होंगे। सत्ता के साथ बड़ी जिम्मेदारी आती है। तो इसे समझदारी से उपयोग करें आप इसका उपयोग कर रहे हैं। यह eval () फ़ंक्शन से संबंधित नहीं है, लेकिन इस लेख में बहुत अच्छी जानकारी है: http://blogs.popart.com/2009/07/javascript-injection-attacks/ यदि आप eval की मूल बातें खोज रहे हैं () यहाँ देखें: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval


2

जावास्क्रिप्ट इंजन में कई प्रदर्शन अनुकूलन हैं जो यह संकलन चरण के दौरान करता है। इनमें से कुछ उबालने के लिए अनिवार्य रूप से सांख्यिकीय रूप से कोड का विश्लेषण करने में सक्षम होते हैं, क्योंकि यह सभी चर और फ़ंक्शन घोषणाएं हैं, ताकि निष्पादन के दौरान पहचानकर्ताओं को हल करने में कम प्रयास लगे।

लेकिन अगर इंजन कोड में एक इवैल (..) पाता है, तो अनिवार्य रूप से यह मान लेना होगा कि पहचानकर्ता स्थान के बारे में उसकी सभी जागरूकता अमान्य हो सकती है, क्योंकि यह समय पर पता नहीं चल सकता है कि आप कोड (eval) पास कर सकते हैं। लेक्सिकल स्कोप को संशोधित करने के लिए, या जिस ऑब्जेक्ट से आप गुजर सकते हैं, उसके कंटेंट को सलाह देने के लिए एक नया लेक्सिकल स्कोप बनाएं।

दूसरे शब्दों में, निराशावादी अर्थों में, यह जो अनुकूलन करता है, उनमें से अधिकांश व्यर्थ होते हैं यदि eval (..) मौजूद है, तो यह बस अनुकूलन का प्रदर्शन नहीं करता है।

यह सब समझाता है।

संदर्भ:

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


कोई भी जावास्क्रिप्ट इंजन 100% गारंटी के साथ कोड में नहीं पाया जा सकता है और इसे खाली नहीं कर सकता है। इसलिए, यह किसी भी समय इसके लिए तैयार होना चाहिए।
जैक गिफिन

2

यह हमेशा एक बुरा विचार नहीं है। उदाहरण के लिए, कोड पीढ़ी। मैंने हाल ही में हाइपरबर्स नामक एक लाइब्रेरी लिखी है जो वर्चुअल-डोम और हैंडलबार्स के बीच की खाई को पाटती है । यह एक हैंडलबार टेम्पलेट को पार्स करके और इसे में परिवर्तित करके करता है हाइपरस्क्रिप्ट में जो बाद में वर्चुअल-डोम द्वारा उपयोग किया जाता है। हाइपरस्क्रिप्ट को पहले एक स्ट्रिंग के रूप में उत्पन्न किया जाता है और इसे वापस करने से पहले, eval()इसे निष्पादन योग्य कोड में बदल दिया जाता है। मैंने पायाeval() इस विशेष स्थिति में बुराई के ठीक विपरीत है।

मूल रूप से

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

इसके लिए

(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() तरह की स्थिति में कोई समस्या नहीं है क्योंकि आपको केवल एक बार उत्पन्न स्ट्रिंग की व्याख्या करने की आवश्यकता होती है और फिर कई बार निष्पादन योग्य आउटपुट का पुन: उपयोग होता है।

आप देख सकते हैं कि यदि आप यहां उत्सुक हैं तो कोड पीढ़ी कैसे प्राप्त की गई थी ।


2

मैं यह कहना चाहूंगा कि यदि आप eval()जावास्क्रिप्ट का उपयोग करते हैं जो ब्राउज़र में चलाया जाता है तो यह वास्तव में कोई मायने नहीं रखता है। * (चेतावनी)

सभी आधुनिक ब्राउज़रों में एक डेवलपर कंसोल होता है जहाँ आप किसी भी तरह से मनमाने तरीके से जावास्क्रिप्ट निष्पादित कर सकते हैं और कोई भी अर्ध-स्मार्ट डेवलपर आपके JS स्रोत को देख सकता है और इसके लिए जो कुछ भी आवश्यक है उसे देव कंसोल में डाल सकता है।

* जब तक आपके सर्वर एंडपॉइंट्स में यूजर सप्लाई वैल्यूज की सही वैलिडेशन और सैनिटेशन है, तब तक यह मायने नहीं रखना चाहिए कि आपके क्लाइंट साइड जावास्क्रिप्ट में पार्स और एवैलिड क्या होता है।

आप अगर यह उपयोग करने के लिए उपयुक्त है पूछने के लिए थे, तो eval()फिर भी PHP में, जवाब है नहीं , जब तक आप श्वेत सूची किसी भी मान अपने eval बयान के लिए पारित किया जा सकता है।


न केवल एक देव कंसोल है, आप जावास्क्रिप्ट में भी टाइप कर सकते हैं: पृष्ठ पर अपना स्वयं का कंसोल बनाने के लिए url बार में कोड यदि कोई नहीं है, जैसा कि पुराने IE ब्राउज़र और मोबाइल उपकरणों पर होता है।
दिमित्री

1

मैं कुछ भी कहने का प्रयास नहीं करूंगा, जिसमें कहा गया है, लेकिन मैं इसे () (जहाँ तक मुझे पता है) किसी भी तरह से नहीं किया जा सकता है। इसे कोड करने के शायद अन्य तरीके हैं, और शायद इसे अनुकूलित करने के तरीके हैं, लेकिन यह स्पष्टता के लिए किसी भी घंटियाँ और सीटी के बिना स्पष्टता के उपयोग को स्पष्ट करने के लिए बिना किसी घंटी और सीटी के किया जाता है जो वास्तव में कोई अन्य विकल्प नहीं है। वह है: डायनेमिक (या अधिक सटीक) प्रोग्राम-निर्मित ऑब्जेक्ट नाम (मानों के विपरीत)।

//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);

संपादित करें: वैसे, मैं सुझाव नहीं दूंगा (सभी सुरक्षा कारणों से बताया गया है कि आप उपयोगकर्ता इनपुट पर ऑब्जेक्ट नामों को आधार बनाते हैं)। मैं किसी भी अच्छे कारण की कल्पना नहीं कर सकता, जो आप करना चाहते हैं। फिर भी, मैंने सोचा कि मैं इसे इंगित करूँगा कि यह एक अच्छा विचार नहीं होगा :)


3
इस के साथ किया जा सकता है namespaceToTest[namespaceParts[i]], यहाँ कोई ज़रूरत नहीं है, इसलिए if(typeof namespaceToTest[namespaceParts[i]] === 'undefined') { namespaceToTest[namespaceParts[i]] = {};एकमात्र अंतरelse namespaceToTest = namespaceToTest[namespaceParts[i]];
user2144406

1

कचरा इकठा करना

ब्राउज़र कचरा संग्रह का कोई पता नहीं है अगर कोड का जो eval'ed है, उसे मेमोरी से हटाया जा सकता है, इसलिए यह केवल तब तक संग्रहीत रहता है जब तक कि पृष्ठ को फिर से लोड नहीं किया जाता है। बहुत बुरा नहीं है यदि आपके उपयोगकर्ता शीघ्र ही आपके पृष्ठ पर हैं, लेकिन यह वेबएप के लिए एक समस्या हो सकती है।

यहाँ समस्या का डेमो करने के लिए एक स्क्रिप्ट है

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

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

उपरोक्त कोड के रूप में कुछ सरल है, ऐप के मरने तक मेमोरी की एक छोटी मात्रा को स्टोर करने का कारण बनता है। यह तब और खराब होता है जब विकसित स्क्रिप्ट एक विशाल कार्य है, और इसे अंतराल पर कहा जाता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.