SORU
14 EKİM 2013, PAZARTESİ


Dolaylı eval sıkı modu çağrısı

eval() non-sıkı bağlamlarda nasıl işlediğini anlıyorum, ancak katı modda eval() kullanma durumunda tamamen benim aklım karıştı. eval() doğrudan genel kapsamda çağrıldığında, değişkenler eval() yeni kapsamı içinde tuttu

'use strict';
eval('var a = 1;');
console.log(a); // ReferenceError: a is not defined

Eğer bir yapıyorum ancakdolaylıglobal kapsam eval() (aynı şey, değil mi?). katı modda Eğer bana, this JSFiddle bakın inanmıyorsun olursa. () gibi davranır:

'use strict';
(0, eval)('var a = 1;'); // indirect call to eval
console.log(a); // 1???

Eğer (0, eval) ne yaptığını anlamıyorsun bile, Why does google main page use (0, obj.func)(args) syntax? bkz.

En azından benim hesabıma göre anlayış nasıl eval() gerektiği için işi sıkı modda, bunu demek için (olursa olsun eval() denen, doğrudan veya dolaylı olarak) yeni bir kapsam için değişkenler tanımlanır eval() çağrı, ancak bu değil, galiba burada. Belirtimi şunları söyledi:

10.4.2 Girme Eval Kod

Aşağıdaki adımları kontrol eval kod için yürütme içeriği girdiğinde gerçekleştirilir:

  1. Eğer bağlam çağırmak yok ya eğer eval kodu eval işlevi doğrudan bir çağrı (15.1.2.1.1) tarafından değerlendirilir, değil o zaman

    bir. Eğer küresel bir yürütme içeriği eval kodunu kullanarak olsaydı gibi yürütme içeriği yenidenC10.4.1.1 açıklandığı gibi.

  2. Başka

    bir. Arama yürütme içeriği ThisBinding aynı değeri ThisBinding ayarlayın.
    b. Arama yürütme içeriği LexicalEnvironment aynı değeri LexicalEnvironment ayarlayın.
    c. Arama yürütme içeriği VariableEnvironment aynı değeri VariableEnvironment ayarlayın.

  3. Eval kodu strict code, daha sonra ise

    bir. İzin verinstrictVarEnvNewDeclarativeEnvironment LexicalEnvironment geçen argüman olarak arama sonucu.
    b. LexicalEnvironment ayarlayınstrictVarEnv.
    c. VariableEnvironment ayarlayınstrictVarEnv.

  4. 10.5 eval kodunu kullanarak açıklandığı gibi Declaration Binding Instantiation gerçekleştirin.

Bu durumda tüm büyük tarayıcıları da dahil olmak üzere (ancak bunlarla sınırlı değildir) Internet Explorer 10, Chrome ve Firefox 30 24 - hepsini aynı davranış, pek sanmıyorum, büyük ihtimalle bu bir hata. İkimiz de aynı şeyi yapmak istedim, ve neden bu durumda değil mi?

Not:lütfensakın bana kullanma eval() (Evet, biliyorum, "tehlike" kullanarak eval()) - ben sadece istiyorsun anlıyorum mantığı bu işin arkasında olan bir bilmece benim için.

CEVAP
14 EKİM 2013, PAZARTESİ


tl;dr

(0, eval)('var a = 1;'); ikinci durumda aslında doğrudan bir çağrı değildir.

Bu daha yaygın olarak görebilirsiniz:

(function(){ "use strict"
    var x = eval;
    x("var y = 10"); // look at me all indirect
    window.y;// 10
    eval("var y = 11");
    window.y;// still 10, direct call in strict mode gets a new context
})();

Sorun görülebilir:

Eval kod katı kod, (bana: bağlam düzeltme) ise

Ama sıkı eval kod olarak tanımlanır:

Eval kod Kullanımı Sıkı Direktif içeren bir Yönerge, bir Prolog ile başlar, ya da eğer eval çağrısı doğrudan bir çağrı ise sıkı eval kod.

Çağrı değil, doğrudan yana, eval kodunu sıkı eval kod ve yürütme genel kapsamlı.


Tüm büyük karlar elde edebilirsiniz.

"Eval Kodu" eval. doğrudan veya dolaylı çağrı daha genel.

Kontrol edelim tam özellikleri for the eval function

15.1.2.1 eval (x)

Eval fonksiyonunu tek bir argüman ile x çağrıldığında, aşağıdaki adımlar takip edilir:

  1. Eğer Türü(x) Dize ise, x dönün.

  2. Prog bir Program olarak x ayrıştırma sonucu ECMA kodu olalım. Eğer ayrıştırma başarısız olursa, SyntaxError istisnası (ama Ayrıca bakınız Madde 16) atmak.

  3. EvalCtx sonucu olsunyeni bir yürütme içeriği kurmak(10.4.2) eval kod prog.

  4. Sonuç program prog değerlendirme sonucu olsun.

  5. Çalışan yürütme bağlam evalCtx, önceki yürütme içeriği geri çıkın. ...

Yani, 10.4.2, bize, keşfedelim, özel içeri ilk tümcesi bak sana gösterdi:

Yoksa arama bağlam ya da eğer eval kod değil değerlendirilmiş tarafından doğrudan bir çağrı (15.1.2.1.1) eval fonksiyonu sonra ... Yeniden yürütme içeriği sanki bir genel yürütme içeriği

Direct call nedir?

Eval işlevi doğrudan bir çağrı iki aşağıdaki koşulları karşılayan bir CallExpression olarak ifade edilir:

Bu CallExpression içinde MemberExpression değerlendirilmesi sonucu Referans taban değeri kaydı gibi bir ortam var ve referans ismini"". eval

Soyut işlem, bu Başvuru ile GetValue argüman olarak arama sonucu standart yerleşik işlev 15.1.2.1 tanımlanır.

Her iki durumda da MemberExpression nedir?

eval('var a = 1;'); referans bir adı var değerlendirme sonucu doğrusu eval GetValue çözünürlük arama fonksiyonuna döner.

(0, eval)('var a = 1;'); üye ifade değerlendirme sonucudeğilbaşvuru isim eval. (Gerçi GetValue) işlevi yerleşik çözmek.

Referans isimleri ne?

Bölüm 8.7 in the spec anlatıyor:

Başvuru çözülmüş adı bağlayıcıdır. Başvuru üç bileşen, temel değeri, belirtilen ada ve Boolean değerli sıkı referans bayrağı oluşmaktadır. Temel değeri tanımsız, bir Nesne, bir Boolean, bir Dize, bir Sayı veya bir ortam kaydı (10.2.1). Tanımsız bir taban değer bir başvuru bağlama çözülemedi gösterir. Başvurulan adı bir Dize.

Bu bize GetReferencedName içine bakmak gerekir:

GetReferencedName(V). Döner referans V. başvurulan ad bileşeni

İşlevini değerlendirirken 27 ** ifade doğru olduğu sürece, bu adlandırma aslında, çünkü dolaylı bir çağrıdır.

Function yapıcı yerine teklif:) olabilir miyim?

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • Bigapplemagic

    Bigapplemagi

    22 EYLÜL 2011
  • Fuse

    Fuse

    21 Kasım 2005
  • GavinMichaelBooth

    GavinMichael

    26 AĞUSTOS 2006