2012-09-24 13 views
14

यह कोड एक त्रुटि क्यों फेंक देता है?(फ़ंक्शन eval() {}) फ़ंक्शन बॉडी सख्त मोड में है तो एक वाक्यविन्यास त्रुटि फेंकता है?

// global non-strict code 
(function eval() { 'use strict'; }); 

लाइव डेमो:http://jsfiddle.net/SE3eX/1/

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

सख्त मोड नियम यहां हैं: http://ecma-international.org/ecma-262/5.1/#sec-C

प्रासंगिक गोली यह एक (यह सूची में अंतिम एक है) है:

It is a SyntaxError to use within strict mode code the identifiers eval or arguments as the Identifier of a FunctionDeclaration or FunctionExpression or as a formal parameter name (13.1). Attempting to dynamically define such a strict mode function using the Function constructor (15.3.2) will throw a SyntaxError exception.

सूचना कैसे यह नियम केवल लागू होता है अगर समारोह घोषणा/अभिव्यक्ति स्वयं सख्त कोड में दिखाई देती है, जो उपरोक्त मेरे उदाहरण में नहीं है।

लेकिन यह अभी भी एक त्रुटि फेंकता है? क्यूं कर?

+3

बस पूरी तरह से अनुमान लगाते हुए, लेकिन शायद इस तथ्य के साथ कुछ करने के लिए है कि एक * अभिव्यक्ति * में, एक नाम के साथ एक फ़ंक्शन इंस्टेंटेशन अभिव्यक्ति उस नाम को केवल * * के भीतर बांधती है; दूसरे शब्दों में, यह आंतरिक रूप से है जैसे कि 'var' घोषणा के लिए कुछ जादू तरीका था जो फ़ंक्शन के संदर्भ में प्रारंभिक स्थानीय चर बनाने के लिए था। इस प्रकार, ऐसा लगता है कि आप स्थानीय प्रतीक "eval" को स्थानीय रूप से बांधने का प्रयास कर रहे थे। – Pointy

+0

@ पॉइंटी अच्छा संकेत। मुझे उस परिदृश्य में वास्तव में क्या चल रहा है यह स्थापित करने के लिए मानक जांचना होगा ... –

+1

आपको एक ही त्रुटि संदेश मिलता है (सिंटेक्स त्रुटि: फंक्शन का नाम सख्ती मोड में eval या तर्क नहीं हो सकता है) केवल 'function eval() के साथ {'सख्त उपयोग करें'; }; ' – some

उत्तर

10

§13.1 की रूपरेखा क्या इस तरह तुम्हारा के रूप में मामलों में तो होना ही चाहिए:

  • It is a SyntaxError if any Identifier value occurs more than once within a FormalParameterList of a strict mode FunctionDeclaration or FunctionExpression.
  • It is a SyntaxError if the Identifier "eval" or the Identifier "arguments" occurs within a - FormalParameterList of a strict mode FunctionDeclaration or FunctionExpression.
  • It is a SyntaxError if the Identifier "eval" or the Identifier "arguments" occurs as the Identifier of a strict mode FunctionDeclaration or FunctionExpression.

जोर मेरा। आपका सख्त मोड समारोह के पहचानकर्ताeval, इस प्रकार, यह एक SyntaxError है। खेल खत्म। क्यों के ऊपर एक है


देखने के लिए "सख्त मोड समारोह अभिव्यक्ति," §13 (फंक्शन परिभाषा) में अर्थ परिभाषाओं को देखो:

The production
FunctionExpression : functionIdentifieropt(FormalParameterListopt) {FunctionBody} is evaluated as follows:

  1. Return the result of creating a new Function object as specified in 13.2 with parameters specified by FormalParameterListopt and body specified by FunctionBody. Pass in the LexicalEnvironment of the running execution context as the Scope. Pass in true as the Strict flag if the FunctionExpression is contained in strict code or if its FunctionBody is strict code.

जोर मेरा। उपर्युक्त दिखाता है कि फ़ंक्शन अभिव्यक्ति (या घोषणा) कैसे सख्त हो जाती है।

  1. यह एक use strict संदर्भ से कहा जाता है: क्या यह कहता है (सादा अंग्रेजी में) है कि एक FunctionExpression दो में strict परिदृश्यों है।
  2. इसका फ़ंक्शन बॉडी use strict से शुरू होता है।

आपका भ्रम सोच से उत्पन्न होती है कि केवल समारोह शरीर, strict है जब वास्तव में, पूरे समारोह अभिव्यक्तिstrict है। आपका तर्क, सहज ज्ञान युक्त, यह नहीं है कि जेएस कैसे काम करता है।


यदि आप सोच रहे हैं कि ईसीएमएस्क्रिप्ट इस तरह क्यों काम करता है, तो यह बहुत आसान है।मान लीजिए कि हमें इस है:

// look ma, I'm not strict 
(function eval() { 
    "use strict"; 
    // evil stuff 
    eval(); // this is a perfectly legal recursive call, and oh look... 
      // ... I implicitly redefined eval() in a strict block 
    // evil stuff 
})(); 

शुक्र है, इसके बाद के संस्करण कोड क्योंकि पूरे समारोह अभिव्यक्तिstrict रूप में चिह्नित किया गया है फेंक देते हैं।

+1

ने इसे खींचा। यह वास्तव में क्या हो रहा है – Claudiu

+0

तो एक फ़ंक्शन अभिव्यक्ति जो गैर-सख्त कोड में होती है, लेकिन जिसका फ़ंक्शन बॉडी सख्त कोड है, एक "सख्त मोड फ़ंक्शन अभिव्यक्ति" है? क्या आप इस परिभाषा को मानक में पा सकते हैं, कृपया? –

+1

@ ŠimeVidas http://ecma-international.org/ecma-262/5.1/#sec-10.1.1 - "फंक्शन कोड जो फंक्शनक्लेक्शनेशन, फंक्शन एक्स्पेरेशन, या एक्सेसर प्रॉपर्टीएसिग्मेंटमेंट का हिस्सा है ** सख्त फ़ंक्शन कोड ** है इसका फ़ंक्शन डिस्क्लेरेशन, ** फ़ंक्शनएक्सप्रेस **, या प्रॉपर्टी एसिग्मेंट सख्त मोड कोड या ** में निहित है। यदि फ़ंक्शन कोड डायरेक्टिव प्रस्तावना से शुरू होता है जिसमें एक सख्त निर्देश ** का उपयोग होता है। " – Pete

1

मेरा अनुमान है कि यह है कि यह क्योंकि समारोह eval अंदर एक त्रुटि फेंकता समारोह में ही जो अब सख्त मोड के उल्लंघन में है को इंगित करेंगे।

3

शानदार सवाल!

तो आप वास्तव में process for declaring a function में देखने की जरूरत है आपकी समस्या का जवाब खोजने के लिए (विशेष रूप से, 3-5 चरणों - जोर जोड़ा):

  1. ...
  2. ...
  3. Call the CreateImmutableBinding concrete method of envRec passing the String value of Identifier as the argument.
  4. Let closure be the result of creating a new Function object as specified in 13.2 with parameters specified by FormalParameterListopt and body specified by FunctionBody. Pass in funcEnv as the Scope.Pass in true as the Strict flag if the FunctionExpression is contained in strict code or if its FunctionBody is strict code.
  5. Call the InitializeImmutableBinding concrete method of envRec passing the String value of Identifier and closure as the arguments.

तो, क्या होता है कि eval के आपके उपयोग बाध्यकारी चरण 3 में बनने पर कोई समस्या नहीं है, लेकिन एक बार यह चरण 5 पर पहुंचने के बाद, यह eval के बाध्यकारी को सख्त शब्दावली वातावरण (यानी eval पर कुछ निर्दिष्ट करने) को शुरू करने का प्रयास कर रहा है, जिसकी अनुमति नहीं है क्योंकि हम हैं चरण 4 के बाद एक सख्त संदर्भ में।

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

अद्यतन:

@DavidTitarenco के रूप में कहे अनुसार, इस स्पष्ट रूप से खंड 13.1 में कवर किया जाता है (अनुभाग 13 में निहित प्रतिबंध के अलावा)।

+0

एचएम, मुझे नहीं लगता कि 'प्रारंभिक Immutable बाइंडिंग' असाइनमेंट ऑपरेटर का उपयोग करता है। स्रोत कोड में असाइनमेंट ऑपरेटर "मौजूद" है, जबकि 'प्रारंभिक Immutable बाइंडिंग' एक आंतरिक विधि है। मुझे संदेह है कि यह * जावास्क्रिप्ट * में परिभाषित है। –

+0

@ ŠimeVidas आप सही हैं। यह spec के पत्र का उल्लंघन नहीं करता प्रतीत होता है, लेकिन ऐसा लगता है कि यह spec के * भावना * का उल्लंघन करता है। ईसीएमएस्क्रिप्ट के साथ नियमित रूप से नियमित आधार पर आपको कुछ भी ध्यान में रखना है। : -/(यह कोड है, "आपका अनुमान मेरे जैसा अच्छा है" - काश मैं इस सवाल को दो बार बढ़ा सकता हूं)। – Pete

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