2011-01-05 10 views
68

क्या ये दो कार्य दृश्यों के पीछे एक ही काम कर रहे हैं? (एकल कथन कार्यों में)eval() और नया फ़ंक्शन() एक ही चीज़ है?

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')); 
+2

वास्तव में इसका उपयोग jQuery 1.7.2 लाइन 573 में किया जाता है। हालांकि "कुछ सुरक्षा जांच" – PicoCreator

+0

इस चर्चा में 'नया' क्यों माना जाता है? 'फंक्शन' स्पष्ट रूप से 'फ़ंक्शन ऑब्जेक्ट' को तुरंत चालू करता है। 'नया' को छोड़कर कोड बिल्कुल नहीं बदलेगा। यहां एक jsfiddle दिखा रहा है कि: http://jsfiddle.net/PcfG8/ –

उत्तर

87

नहीं, वे समान नहीं हैं।

  • eval() वर्तमान निष्पादन दायरे में एक जावास्क्रिप्ट अभिव्यक्ति के रूप में एक स्ट्रिंग का मूल्यांकन करता है और स्थानीय चर का उपयोग कर सकता है।
  • new Function() एक स्ट्रिंग में संग्रहीत जावास्क्रिप्ट कोड को फ़ंक्शन ऑब्जेक्ट में पार्स करता है, जिसे तब कॉल किया जा सकता है। यह स्थानीय चर का उपयोग नहीं कर सकता क्योंकि कोड एक अलग दायरे में चलता है।

    function test1() { 
        var a = 11; 
        eval('(a = 22)'); 
        alert(a);   // alerts 22 
    } 
    

    तो new Function('return (a = 22);')() इस्तेमाल किया गया, स्थानीय चर a अपने मूल्य को बनाए रखने होगा:

इस कोड पर विचार करें। फिर भी, डगलस क्रॉकफोर्ड जैसे कुछ जावास्क्रिप्ट प्रोग्रामर मानते हैं कि neither should be usedabsolutely necessary तक, और अविश्वसनीय डेटा पर Function कन्स्ट्रक्टर का उपयोग/उपयोग करना असुरक्षित और मूर्ख है।

var func = function(string) { 
    return (new Function('return (' + string + ')')()); 
} 

सूचना है कि समारोह (...)() अंत "()" में है:

+5

"कभी भी इस्तेमाल नहीं किया जाना चाहिए" इतना व्यापक बयान है। इसके बारे में, किसी भी इनपुट को आपके नियंत्रण से बाहर होने पर कभी भी उपयोग नहीं किया जाना चाहिए। ऐसा कहकर, JSON को पार्स करने के अलावा, मुझे इसका उपयोग करने की आवश्यकता नहीं थी। लेकिन मैंने यहां सवालों के जवाब दिए हैं जो वैध उपयोगों की तरह लगते थे, इसमें कुछ ऐसा शामिल था जैसे प्रशासकों को टेम्पलेटिंग कार्यों को उत्पन्न करने की इजाजत दी गई थी जो अंतिम उपयोगकर्ता उपयोग कर सकते थे। इस मामले में इनपुट एक व्यवस्थापक द्वारा उत्पन्न किया गया था, इसलिए यह स्वीकार्य था –

+1

@ जुआन: क्रॉकफोर्ड का मुद्दा यह है कि eval अक्सर दुरुपयोग किया जाता है (आपके परिप्रेक्ष्य पर निर्भर करता है), इसलिए इसे "सर्वोत्तम प्रथाओं" जावास्क्रिप्ट से बाहर रखा जाना चाहिए।हालांकि, मैं सहमत हूं कि यह जेएसओएन या अंकगणित अभिव्यक्ति पार्सिंग के रूप में ऐसे उपयोगों के लिए उपयोगी है जब इनपुट पहली बार सही तरीके से सत्यापित किया जाता है। यहां तक ​​कि क्रॉकफ़ोर्ड भी इसे अपने JSON लाइब्रेरी json2.js में उपयोग करता है। – PleaseStand

+0

तो इसका मतलब यह है कि 'नया फ़ंक्शन (कोड) '' eval (' (function() {'+ code +'})() ') के समान है या' या यह एक बिल्कुल नया निष्पादन संदर्भ है? –

1

उस उदाहरण में, परिणाम समान हैं, हां। आपके द्वारा पारित अभिव्यक्ति निष्पादित करें। यही कारण है कि उन्हें इतना खतरनाक बनाता है।

लेकिन वे घन के पीछे अलग-अलग चीजें करते हैं। new Function(), पीछे के दृश्यों में से एक, आपके द्वारा प्रदान किए जाने वाले कोड से एक अनाम फ़ंक्शन बनाता है, जिसे फ़ंक्शन लागू होने पर निष्पादित किया जाता है।

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

+0

क्या आप थोड़ा और विस्तार कर सकते हैं? क्या वे दोनों रिटर्न स्टेटमेंट में निष्पादित नहीं हैं? क्या फ़ंक्शन() एक eval की तुलना में एक और स्टैक कॉल स्तर का उपयोग करता है? – qwertymk

+0

'क्या फ़ंक्शन() एक eval की तुलना में एक और स्टैक कॉल स्तर का उपयोग करता है?': मुझे ऐसा लगता है, क्योंकि 'eval()' आपके इनपुट से कोई फ़ंक्शन नहीं बनाता है - यह बस इसे निष्पादित करता है। 'नया फ़ंक्शन()' एक नया फ़ंक्शन बनाता है, जिसे उसके बाद आमंत्रित किया जाता है। –

+0

@ सिंपलकोडर: फ़ंक्शन() कॉल स्टैक में कुछ भी नहीं जोड़ता है। केवल तभी जब आप परिणामस्वरूप फ़ंक्शन को कॉल करते हैं। eval एक ही चीज करता है (यदि प्रश्न के संदर्भ में लागू किया गया है) –

2

यदि आपका मतलब है, तो क्या यह वही परिणाम देगा, फिर हाँ ... लेकिन केवल eval (उर्फ, "जावास्क्रिप्ट की इस स्ट्रिंग का मूल्यांकन") बहुत आसान होगा।

संपादित नीचे:

यह कह रही है की तरह है ... इन दोनों गणित की समस्याओं को एक ही कर रहे हैं:

1 + 1

1 + 1 + 1 - 1 + 1 - 1 * 1/1

+0

क्या वे दोनों स्ट्रिंग को फिर से पार्स करते हैं? – qwertymk

+0

वे दोनों स्ट्रिंग को पार्स करेंगे (आपके कोड उदाहरण में)। "री-पार्स" द्वारा आपका क्या मतलब है, यह नहीं पता। –

+1

मुझे यकीन है कि वे दोनों बिंदुओं पर स्ट्रिंग (मूल्यांकन) दोनों बिंदु पर हैं, लेकिन जब आप फ़ंक्शन का आह्वान करते हैं तो 'फ़ंक्शन' ऑब्जेक्ट शायद किसी निजी सदस्य चर में स्ट्रिंग को 'eval' में संग्रहीत करता है। – palswim

6

सं

अपने अद्यतन में, evaluate और func के लिए कॉल एक ही परिणाम का उत्पादन। लेकिन, वे निश्चित रूप से "दृश्यों के पीछे एक ही चीज़ नहीं कर रहे हैं"। func फ़ंक्शन एक नया फ़ंक्शन बनाता है, लेकिन फिर इसे तुरंत निष्पादित करता है, जबकि evaluate फ़ंक्शन बस स्थान पर कोड निष्पादित करता है।

मूल प्रश्न से:

evaluate('0) + (4'); 
func('0) + (4'); 
+0

किसी भी मामले में, दोनों मामलों में सबसे असाधारण लेकिन सभी में खराब अभ्यास हैं। – palswim

+5

ठीक है आपने अपने कार्यान्वयन के अनुसार अपना उदाहरण फहराया। अगर उसने 'वापसी eval (' ('+ string +') ') के रूप में मूल्यांकन लागू किया था, तो फिर वे एक ही परिणाम प्राप्त करेंगे। –

+0

@ जुआन मैंने नहीं सोचा लेकिन हाँ। प्रश्न – qwertymk

6

new Function एक समारोह है कि पुन: उपयोग किया जा सकता है बनाता है:

var evaluate = function(string) { 
    return eval(string); 
} 
var func = function(string) { 
    return (new Function('return (' + string + ')')()); 
} 

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

क्या यह सच है कि वे पर्दे के पीछे कुछ कोड साझा करते हैं? हाँ, बहुत संभावना है। बिल्कुल वही कोड? नहीं, निश्चित रूप से।

मज़े के लिए, यहां एक कार्य बनाने के लिए eval का उपयोग करके मेरा अपना अपूर्ण कार्यान्वयन है। उम्मीद है कि यह अंतर में कुछ प्रकाश डालता है!

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]'); 
} 

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

+0

संपादित क्यों लूप के बजाय 'arguments.slice()' का उपयोग नहीं करते? या यदि तर्क एक वास्तविक सरणी नहीं है, '[] .slice.call (तर्क, 1) '। – Xeoncross

1

बस यहाँ कुछ उदाहरण में प्रयोग किया जाता वाक्य रचना और क्या इसका मतलब है कि बाहर बिंदु करना चाहते हैं। इस वाक्य रचना नए कार्य को निष्पादित और स्ट्रिंग एक समारोह है कि स्ट्रिंग रिटर्न नहीं लौटने के लिए समारोह का कारण होगा, लेकिन अगर आप का उपयोग करें:

var func = function(string) { 
    return (new Function('return (' + string + ')')); 
} 

अब समारोह एक समारोह है कि एक स्ट्रिंग रिटर्न वापस आ जाएगी।

संबंधित मुद्दे