2012-02-02 17 views
68

मैं JavaScript Patterns पढ़ना शुरू करता हूं, कुछ codes ने मुझे भ्रमित कर दिया।(1, eval) ('यह') बनाम eval ('यह') जावास्क्रिप्ट में?

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; 
}()); 
+0

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

उत्तर

81

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

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. क्या परिस्थिति में एक सीधा eval कॉल नहीं वैश्विक क्षेत्र में निष्पादित करता है?
  2. वैश्विक परिस्थिति में एक समारोह के this किस परिस्थिति में वैश्विक वस्तु उत्पन्न नहीं कर सकता है?

कुछ और जानकारी here मिल सकती है।

संपादित

जाहिर है, मेरा पहला सवाल का जवाब है, "लगभग हमेशा"। वर्तमान स्कोप से सीधे 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, false) पर सेट किया जा सकता है, लेकिन जानबूझकर बहुत पर जा सकता है।

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

+3

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

+0

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

+0

मैं केवल एक बार वैध उपयोग में आया - एक स्क्रिप्ट टैग का मूल्यांकन करना जिसे 'आंतरिक एचटीएमएल' – Stoive

7

Q1: एकाधिक लगातार जावास्क्रिप्ट अल्पविराम से अलग बयानों पिछले बयान के मान ले। तो:

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

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

+0

शायद कोई चेक-इन हुक चकमा देने की कोशिश कर रहा है जो '/ eval \ (/ g'? – Stoive

+0

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

+7

ईएस 5 सख्त मोड के साथ इसका कुछ संबंध है। ईएसएआईके ईएस 5 सख्त मोड में कोई भी 'eval''d कोड है वैश्विक संदर्भ या संलग्न संदर्भ के बजाय अपने संदर्भ में निष्पादित किया गया है। इसके आसपास एक तरीका अप्रत्यक्ष रूप से संदर्भ में कोड के रूप में संदर्भित है। –

11
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

29

टुकड़ा,

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

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

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

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

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