2012-09-24 19 views
14

Bu kod neden bir hata veriyor?(işlev durumu() {}) işlev gövdesi sıkı modda olduğunda bir sözdizimi hatası veriyor?

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

Canlı tanıtım:http://jsfiddle.net/SE3eX/1/

Peki, biz burada var adlandırılmış işlev ifadesidir. Bu işlev ifadesinin sıkı olmayan kodda göründüğünü açıkça belirtmek isterim. Gördüğünüz gibi, onun işlev gövdesi sıkı bir koddur.

katı mod kuralları Buradasınız: http://ecma-international.org/ecma-262/5.1/#sec-C

alakalı madde bu bir (listede son kapı) 'dir: bu kural geçerlidir nasıl

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.

Bildirim IF_FUNCTION beyanı/İfadenin kendisi, yukarıdaki örneğimde değil, sıkı bir kodda görünür.

Yine de bir hata mı atıyor? Niye ya?

+3

Sadece burada tamamen tahmin, ama belki de bir * ifadesi *, bir isim ile bir işlev örnekleme ifadesi sadece bu işlevin içinde * adını * bağladığı gerçeğiyle bir ilgisi vardır; Diğer bir deyişle, dahili bir varyasyon, fonksiyona referansla başlatılan bir yerel değişken oluşturmak için bir “var” beyanı için bazı sihirli bir yol varmış gibi. Böylece, küresel sembolü "eval" yerel olarak bağlama girişiminde bulunuyormuşsunuz gibi. – Pointy

+0

@Pointy İyi ipucu. Bu senaryoda tam olarak neler olup bittiğini belirlemek için standardı kontrol etmem gerekecek ... –

+1

Aynı hata mesajını (SyntaxError: İşlev adı, katı modda değerlendirmeler veya argümanlar olmayabilir) yalnızca "function eval() ile") alırsınız. {'katı kullanın'; }; ' – some

cevap

10

§13.1 sizinki gibi durumlarda gerçekleşmesi gerektiğini şeyi özetler:

  • 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.

Vurgu benim. Sıkı mod işlevinizin tanımlayıcısı, eval, dolayısıyla, bir SyntaxError. Oyun bitti. Yukarıda bir neden


§13 (Fonksiyon Tanımı) içinde anlamsal tanımların bakmak "katı mod fonksiyonu ifadesi," görmek için:

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.

Vurgu benim. Yukarıdakiler, bir işlev ifadesinin (veya beyanının) nasıl katı hale geldiğini gösterir. Bu bir use strict bağlamdan denir

  1. : Ne (Türkçesi) diyen bir FunctionExpressionstrict iki senaryo olmasıdır.
  2. İşlev gövdesi use strict ile başlar. aslında, tüm fonksiyon ifadesistrict olduğunda sadece işlev gövdesi, strict olduğunu

Kişisel karışıklık düşünme kaynaklanmaktadır. Mantığınız sezgisel olsa da, JS nasıl çalışır?


ECMAscript'in neden bu şekilde çalıştığını merak ediyorsanız, oldukça basittir.Bu olduğunu varsayalım: tüm işlev ifadesistrict olarak işaretlenir çünkü

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

Neyse ki, yukarıdaki kod atar.

+1

, çivilenmiş. tam olarak burada olan şey budur – Claudiu

+0

Bu nedenle, sıkı olmayan kodda meydana gelen, ancak işlev gövdesi sıkı kod olan bir işlev ifadesi, "katı mod işlev ifadesi" dir? Bu tanımı standartta bulabilir misiniz, lütfen? –

+1

@ ŠimeVidas http://ecma-international.org/ecma-262/5.1/#sec-10.1.1 - "FunctionDeclaration, FunctionExpression veya accessor PropertyAssignment ** öğesinin bir parçası olan işlev kodu, FunctionDeclaration, ** FunctionExpression ** veya PropertyAssignment, sıkı mod kodunda veya **, işlev kodu, Use Strict Directive ** içeren bir Yönerge Prologue ile başlıyorsa. – Pete

1

Bir hatayı attığını tahmin ediyorum çünkü fonksiyonun içinde, şu anda katı modun ihlali yapan işlevin kendisini göstermesi gerek.

3

Harika soru!

Yani aslında process for declaring a function bakmak gerekir sorununuza cevap bulmak için (özellikle 3-5 arasındaki adımları - vurgu eklenmiştir):

  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.

Yani, ne olur olduğunu eval kullanımınız Bağlanma adım 3'te oluşturulduğunda sorun değil, ancak adım 5'i vurduktan sonra, eval bağlayıcılığının sıkı bir sözlük içinde (örneğin eval'a bir şey atayarak) başlatılmasını deniyor, çünkü 4. adımı izleyen sıkı bir bağlamda

Bu kısıtlamanın Yeni bir eval değişkenini başlatırken. İşlev bildirim işleminin 5. adımında gerçekleşen bir Atama işleci olan LeftHandSideExpression olarak kullanılıyor.

Update: @DavidTitarenco belirttiği gibi

, bu açık bir şekilde (kısım 13 örtülü sınırlama ek olarak) bölümünde 13.1 kaplıdır.

+0

Hm, 'InitializeImmutableBinding' öğesinin işlecini kullandığını sanmıyorum. Atama operatörü kaynak kodunda "bulunur", "InitializeImmutableBinding" ise dahili bir yöntemdir. Bunun, * JavaScript'in içinde tanımlandığından şüphe duyuyorum. –

+0

@ ŠimeVidas haklısınız. Spesifikasyon mektubunu ihlal ediyor gibi görünmüyor, ancak speklerin * ruhunu * ihlal ediyor gibi görünüyor. ECMAScript ile çok düzenli olarak hesaba katmanız gereken bir şey var. : -/(bu sizin için "tahmininiz benimki kadar iyi" diye kodluyor - Keşke bu soruyu iki kere alabilirim). – Pete

İlgili konular