(1, eval) ('this') vs eval ('this') जावास्क्रिप्ट में?


85

मैं जावास्क्रिप्ट पैटर्न पढ़ना शुरू करता हूं , कुछ कोड ने मुझे भ्रमित किया।

var global = (function () {
    return this || (1, eval)('this');
}());

यहाँ मेरे सवाल हैं:

Q1:

(1, eval) === eval?

यह क्यों और कैसे काम करता है?

Q2: क्यों नहीं

var global = (function () {
    return this || eval('this');
}());

या

 var global = (function () {
    return this;
}());

मैंने शीर्षक अपडेट किया है क्योंकि यह एक विशिष्ट मामला है। इसके अलावा, कोष्ठक के विशिष्ट प्रकार के लिए कोष्ठक : [] और {} पूरी तरह से अलग हैं :)

जवाबों:


104

(1,eval)पुराने और सादे पुराने के बीच अंतर यह evalहै कि पूर्व एक मूल्य है और उत्तरार्द्ध एक अंतराल है। यह अधिक स्पष्ट होगा यदि यह कुछ अन्य पहचानकर्ता थे:

var x;
x = 1;
(1, x) = 1; //  syntax error, of course!

यह (1,eval)एक ऐसी अभिव्यक्ति है जो पैदावार eval(जैसा कि कहती है, (true && eval)या (0 ? 0 : eval)करेगी), लेकिन यह एक संदर्भ नहीं है eval

तुम क्यो फिकर करते हो?

ठीक है, एक्मा कल्पना एक संदर्भ को eval"प्रत्यक्ष eval कॉल" माना जाता है , लेकिन एक अभिव्यक्ति जो केवल evalएक अप्रत्यक्ष होने के लिए पैदावार देती है - और अप्रत्यक्ष eval कॉल वैश्विक दायरे में निष्पादित करने की गारंटी है।

चीजें जो मुझे अभी भी नहीं पता हैं:

  1. किस परिस्थिति में एक प्रत्यक्ष निकासी कॉल वैश्विक दायरे में निष्पादित नहीं होती है?
  2. thisवैश्विक दायरे में एक समारोह के लिए किस परिस्थिति में वैश्विक वस्तु का उत्पादन नहीं किया जा सकता है?

कुछ और जानकारी यहां दी जा सकती है

संपादित करें

जाहिर है, मेरे पहले सवाल का जवाब है, "लगभग हमेशा"। एक प्रत्यक्ष वर्तमान दायरे evalसे निष्पादित होता है । निम्नलिखित कोड पर विचार करें:

var x = 'outer';
(function() {
  var x = 'inner';
  eval('console.log("direct call: " + x)'); 
  (1,eval)('console.log("indirect call: " + x)'); 
})();

आश्चर्य की बात नहीं (हे-हे), यह प्रिंट करता है:

direct call: inner
indirect call: outer

संपादित करें

अधिक प्रयोग के बाद, मैं प्रावधिक कहना है कि जा रहा हूँ thisकरने के लिए सेट नहीं किया जा सकता nullया undefined। इसे अन्य झूठे मूल्यों (0, '', NaN, असत्य) पर सेट किया जा सकता है, लेकिन केवल बहुत जानबूझकर।

मैं यह कहने जा रहा हूं कि आपका स्रोत एक हल्के और प्रतिवर्ती क्रेनियो-रेक्टल उलटा से पीड़ित है और हास्केल में एक सप्ताह की प्रोग्रामिंग पर विचार करना चाह सकता है।


3
वाह, पूरे नहीं पता था valueबनाम lvalueबात (अच्छी तरह से हो सकता है, व्यवहार में, लेकिन शब्दों में नहीं)। और न ही ES5 eval नियम (ऐसा नहीं है कि मुझे यथोचित उपयोग करने की आवश्यकता है eval)। धन्यवाद!
स्टोव

हाँ, evalबहुत सारे तीखे नुकीले किनारे हैं और केवल एक अंतिम उपाय के रूप में इस्तेमाल किया जाना चाहिए और फिर, बहुत सावधानी से।
मालवोलियो

मैं केवल एक बार एक वैध उपयोग में आया था - एक स्क्रिप्ट टैग का मूल्यांकन करना जो डोम के माध्यम से जोड़ा गया थाinnerHtml
Stoive

1
लैवल्यू के पास प्रत्यक्ष eval का निर्धारण करने के कारण बहुत कम है क्योंकि यह आमतौर पर उस अभिव्यक्ति को संदर्भित करता है जो एक असाइनमेंट के बाईं ओर दिखाई दे सकता है, इसलिए नाम rvalue का विरोध करता है। Eval के लिए एक कॉल केवल 15.1.2.1.1 में सूचीबद्ध शर्तों के तहत प्रत्यक्ष है, जो कहता है कि पहचानकर्ता को होना चाहिए evalऔर CallExpression का सदस्यExpression हिस्सा होना चाहिए और मानक evalफ़ंक्शन को देखें ।
चक

1
@ मालवियो आपको लग रहा है कि लवलीनों को प्रत्यक्ष बनाम अप्रत्यक्ष रूप से कुछ करना है जो वे नहीं करते हैं। evalकॉल एक्सप्रेशन के लक्ष्य के रूप में पहचाने जाने वाले पहचानकर्ता का उपयोग विशेष है। आप कहते हैं कि ECMA व्यवहार करता है को संदर्भित करने के लिए evalविशेष है जो ऐसा नहीं है। यह कॉल एक्सप्रेशन में प्लेसमेंट है जो विशेष है कि एक्सप्रेशन मानक evalफ़ंक्शन का मूल्यांकन करता है। उदाहरण के लिए, var eval = window.eval; eval('1');अभी भी एक प्रत्यक्ष eval है और window.eval('1')भले ही eval इस मामले में एक समान नहीं है।
चक

33

टुकड़ा,

var global = (function () {  
    return this || (1, eval)('this');  
}());  

वैश्विक रूप से सख्त मोड में भी सही ढंग से मूल्यांकन करेगा। गैर-सख्त मोड में मूल्य thisवैश्विक वस्तु है लेकिन सख्त मोड में है undefined। अभिव्यक्ति (1, eval)('this')हमेशा वैश्विक वस्तु होगी। इसका कारण प्रत्यक्ष अप्रत्यक्ष छंदों के आसपास के नियम शामिल हैं eval। डायरेक्ट कॉल evalमें कॉलर की गुंजाइश होती है और स्ट्रिंग बंद होने thisके मूल्य का मूल्यांकन करेगी this। अप्रत्यक्ष evalरूप से वैश्विक दायरे में मूल्यांकन करते हैं जैसे कि उन्हें वैश्विक दायरे में एक फ़ंक्शन के अंदर निष्पादित किया गया था। चूंकि वह फ़ंक्शन स्वयं एक सख्त-मोड फ़ंक्शन नहीं है, इसलिए वैश्विक ऑब्जेक्ट को पास किया जाता है thisऔर फिर अभिव्यक्ति 'this'वैश्विक ऑब्जेक्ट का मूल्यांकन करती है। अभिव्यक्ति (1, eval)को मजबूर करने के लिए सिर्फ एक फैंसी तरीका हैeval अप्रत्यक्ष होना और वैश्विक वस्तु को वापस करना।

A1: अप्रत्यक्ष कविता प्रत्यक्ष कॉल के आसपास विशेष नियमों के कारण (1, eval)('this')समान नहीं eval('this')है eval

A2: मूल सख्त मोड में काम करता है, संशोधित संस्करण नहीं है।


12

Q1:

मुझे लगता है कि जेएस में यह अल्पविराम ऑपरेटर का एक अच्छा उदाहरण है। मुझे इस लेख में अल्पविराम ऑपरेटर के लिए स्पष्टीकरण पसंद है: http://javascriptweblog.wordpress.com/2011/04/04/the-javascript-comma-operator/

अल्पविराम ऑपरेटर अपने दोनों ऑपरेंड (बाएं से दाएं) का मूल्यांकन करता है और दूसरे ऑपरेंड का मान लौटाता है।

Q2 के लिए:

(1, eval)('this')को अप्रत्यक्ष eval कॉल माना जाता है, जो ES5 विश्व स्तर पर कोड निष्पादित करता है। तो परिणाम वैश्विक संदर्भ होगा।

Http://perfectionkills.com/global-eval-what-are-the-options/#evaling_in_global_scope देखें


7

Q1: एक कॉमा द्वारा अलग किए गए कई लगातार जावास्क्रिप्ट स्टेटमेंट अंतिम स्टेटमेंट का मान लेते हैं। इसलिए:

(1, eval)पिछले एक का मान लेता है जो फ़ंक्शन का एक संदर्भ है eval()। यह जाहिरा तौर पर यह इस तरह से करता है कि eval()कॉल को एक अप्रत्यक्ष eval कॉल में बनाया जाता है जिसका मूल्यांकन ES5 में वैश्विक दायरे में किया जाएगा। विवरण यहाँ समझाया गया है

Q2: कुछ वातावरण होना चाहिए जो एक वैश्विक परिभाषित नहीं करता है this, लेकिन परिभाषित करता है eval('this')। यही एकमात्र कारण है कि मैं इसके लिए सोच सकता हूं।


शायद किसी चेक-इन हुक को चकमा देने की कोशिश कर रहा है जो कि नापसंद है /eval\(/g?
फाइव

@Stoive - हाँ, मैं भी इस तरह से कुछ के बारे में सोच रहा था। यदि चेकइन हुक नहीं है, तो प्रक्रिया में कुछ फिल्टर कहीं (शायद कम से कम)।
jfriend00

7
यह ES5 सख्त मोड के साथ कुछ करना है। ES5 सख्त मोड में AFAIK किसी भी eval'डी कोड को वैश्विक संदर्भ या संलग्न संदर्भ के बजाय अपने संदर्भ में निष्पादित किया जाता है। इसका एक तरीका अप्रत्यक्ष रूप से इसे संदर्भित करना है जैसा कि प्रश्न में कोड करता है।
क्रिस्टियन सांचेज़


CDSanchez और @ Saxoier से जानकारी शामिल करने के लिए मेरे उत्तर को अपडेट किया गया। धन्यवाद।
jfriend00
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.