क्या eval () और नया फंक्शन () एक ही बात है?


92

क्या ये दोनों कार्य पर्दे के पीछे एक ही काम कर रहे हैं? (एकल कथन कार्यों में)

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

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

2
newइस चर्चा में क्यों माना जाता है? Functionसंक्षेप में तात्कालिकता एक function object। बहिष्करण newकोड को बिल्कुल भी नहीं बदलेगा। यहाँ एक jsfiddle प्रदर्शित है कि: jsfiddle.net/PcfG8
ट्रैविस जे

जवाबों:


117

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

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

इस कोड पर विचार करें:

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

यदि new Function('return (a = 22);')()उपयोग किया जाता है, तो स्थानीय चर aइसके मूल्य को बनाए रखेगा। फिर भी, कुछ जावास्क्रिप्ट प्रोग्रामर जैसे डगलस क्रॉकफोर्ड का मानना ​​है कि जब तक पूरी तरह से आवश्यक नहीं है , तब तक उपयोग नहीं किया जाना चाहिए और अविश्वसनीय डेटा पर निर्माणकर्ता का उपयोग करना / उपयोग करना असुरक्षित और नासमझ है।Function


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

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

तो इसका मतलब है कि करता है new Function(code)के रूप में ही है eval('(function(){'+code+'})()')या यह एक पूरी तरह से नए निष्पादन संदर्भ है?
जॉर्ज मौअर

5
@GeorgeMauer: मुझे लगता है कि आप का मतलब है eval('(function(){'+code+'})'), जो एक फ़ंक्शन ऑब्जेक्ट लौटाएगा। एमडीएन के अनुसार , "फ़ंक्शन कंस्ट्रक्टर के साथ बनाए गए फ़ंक्शंस उनके निर्माण संदर्भों के लिए नज़दीकियां पैदा नहीं करते हैं; वे हमेशा विंडो संदर्भ में चलते हैं (जब तक कि फ़ंक्शन बॉडी" उपयोग सख्त "के साथ शुरू नहीं होती है; कथन, जिस संदर्भ में संदर्भ अनिर्धारित है) । "
PleaseStand

6

नहीं।

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

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

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

ये आपको बहुत अलग परिणाम देंगे:

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

किसी भी मामले में, दोनों ही सभी मामलों में सबसे खराब व्यवहार हैं।
पालस्विम ५'११

8
वैसे आपने अपने उदाहरण को उसके कार्यान्वयन के अनुसार बना दिया। यदि उन्होंने मूल्यांकन लागू किया return eval('(' + string + ')');होता तो वे उसी परिणाम प्राप्त करते।
जुआन मेंडेस

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

6

new Functionएक फ़ंक्शन बनाता है जिसका पुन: उपयोग किया जा सकता है। 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]');
}

इस और नए फ़ंक्शन के बीच सबसे बड़ा अंतर यह है कि फ़ंक्शन लेक्सिकली स्कोप नहीं है। तो यह चर और मेरा बंद करने के लिए उपयोग नहीं होगा।


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

3

बस यहाँ उदाहरणों में प्रयुक्त कुछ वाक्यविन्यास को इंगित करना चाहते हैं और इसका क्या अर्थ है:

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

ध्यान दें कि फ़ंक्शन (...) () में अंत में "()" है। यह सिंटैक्स नए फ़ंक्शन को निष्पादित करने और स्ट्रिंग को वापस करने वाले फ़ंक्शन को वापस करने के लिए फंक का कारण होगा जो स्ट्रिंग लौटाता है, लेकिन यदि आप निम्न का उपयोग करते हैं:

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

अब फंक एक फ़ंक्शन लौटाएगा जो एक स्ट्रिंग लौटाता है।


2

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

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

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

1 + 1

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


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

वे दोनों स्ट्रिंग को पार्स करेंगे (आपके कोड उदाहरण में)। "री-पार्स" से आपका क्या मतलब है, यह नहीं जानते।
तीमुथियुस खौरी ५'११ को

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

1

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

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

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


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

Does the Function() one use another stack call level than eval?: मैं ऐसा मान सकता हूं, क्योंकि eval()आपके इनपुट से कोई फ़ंक्शन नहीं बनता है - यह सिर्फ इसे निष्पादित करता है। new Function()एक नया फ़ंक्शन बनाता है, जिसे वह तब इनवॉइस करता है।
क्रिस लाप्लांटे

@SimpleCoder: फ़ंक्शन () कॉल स्टैक में कुछ भी नहीं जोड़ता है। यदि आप परिणामी फ़ंक्शन को कॉल करते हैं तो ही। eval वही काम करता है (यदि प्रश्न के संदर्भ में लागू किया जाता है)
जुआन मेंडेस
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.