ES6 hemen çalıştırılan ok işlevi


149

Bu neden bir Node.jskonsolda çalışıyor (4.1.1 ve 5.3.0'da test edildi) ancak tarayıcıda çalışmıyor (Chrome'da test edildi)? Bu kod bloğu, günlüğe kaydedilen anonim bir işlev oluşturmalı ve çağırmalıdır Ok.

() => {
  console.log('Ok');
}()

Ayrıca, yukarıda iken eserlerinde Düğüm içinde, bu işe yaramazsa:

n => {
  console.log('Ok');
}()

Ne de bu:

(n) => {
  console.log('Ok');
}()

Garip olan şey, parametre eklendiğinde SyntaxErrorhemen çağrılan kısma a atar .


8
İyi soru. Hem parametreli versiyonları Babel ile çalışmak
CodingIntrigue

2
İlgisiz, (n => { console.log("Ok"); })();işe yarıyor mu?
CodingIntrigue

Evet (n => { console.log("Ok"); })(), Chrome geliştirme konsolunda bile çalışıyor
XCS

ve böylece, 3 yıl sonra, cevap nedir? şüphesiz aşağıdaki 3 cevaptan biri kabul edilmelidir?!
joedotnot

@joedotnot Net bir cevap alamadım, çoğunlukla Node.js'de garip bir uygulama oldu. Görünüşe göre Node.jsilk sürümün son sürümü artık çalışmıyor.
XCS

Yanıtlar:


194

Bir isme ihtiyaç duymayan ve geçerli bir JavaScript yapan işlev tanımı yerine bir işlev ifadesi yapmanız gerekir.

(() => {
  console.log('Ok');
})()

IIFE'ye eşdeğerdir

(function(){
   console.log('Ok')
})();

Bunun Node.js'de çalışmasının ancak kromda çalışmamasının olası nedeni, ayrıştırıcının onu kendi kendini yürütme işlevi olarak yorumlamasıdır.

function() { console.log('hello'); }();

içinde çalışıyor Node.jsBu fonksiyon ifadesi ve krom ve firefox ve tarayıcı yorumladığını çoğu bu yoldur. Manuel olarak çağırmanız gerekir.

Ayrıştırıcıya bir işlev ifadesi beklemesini söylemenin en yaygın olarak kabul edilen yolu, ifadeyi yalnızca çözüm ortaklarına sarmaktır, çünkü JavaScript'te çözüm ortakları ifadeler içeremez. Bu noktada, ayrıştırıcı işlev anahtar sözcüğüyle karşılaştığında, bunu işlev bildirimi olarak değil bir işlev ifadesi olarak ayrıştırmayı bilir.

İlgili parametrized sürümü , bu işe yarar.

((n) => {
  console.log('Ok');
})()

4
İlk örnek çalışır Node.jsve aslında değeri günlüğe kaydeder. Benim sorum neden işe yarıyor? Ve parametreyi eklediğimde neden olmasın?
XCS

1
Ben oldukça tanıdık IIFEve kodumu düzeltmek için biliyorum. Örneğin parametre eklenmediğinde neden parametre eklenmediğinde neden IIFEçalışmadığımı merak ettim n.
XCS

3
Ben aşağıya oy vermedim, ama soru şudur: Parametreli sürüm, bir parametre olmadan tam olarak aynı tanım olduğunda neden Düğümde çalışmıyor - anonim işlevlerin Düğüm / Chrome uygulamaları arasındaki farkı sormuyor
CodingIntrigue

1
Bilmek iyi ama daha önce de belirtildiği gibi soruyu cevaplamıyor, neden parametrelenmemiş sürüm bir parametre olmadan tam olarak tanımlandığında
Düğümde

Ancak function(){}()ok işlevlerinin eşdeğeri nedir? Ben fonksiyon nesnesi maruz fonksiyon ifadeleri buna karşı korumak istiyorum.
dabadaba

18

Bunların hiçbiri parantez olmadan çalışmamalıdır.

Neden?

Çünkü spec göre:

  1. ArrowFunction , Atama İfadesi altında listelenir
  2. A LHS CallExpression a olmalıdır MemberExpression , SuperCall veya CallExpression

Yani bir ArrowFunction a lhs olamaz CallExpression .


Bunun etkili bir nasıl gelir =>, yorumlanması gerektiği o atama operatörleri olarak düzeyinin aynı türden çalışır olmasıdır =, +=vb

anlam

  • x => {foo}() vermez hale(x => {foo})()
  • Tercüman bunu x => ({foo}())
  • Bu yüzden hala bir SyntaxError
  • Böylece tercüman, (yanlış olması gerektiğine karar verir ve bir SyntaxError atar

Bu konuda Babel'de bir hata oluştu burada da.


Bunlar bazı geçerli noktalar, ancak ilk çalışan sürümü değiştirmeye çalışırsam: () => ({console.log('Ok')}())artık çalışmıyor. Yani gerçekten bu şekilde yorumlamıyor.
XCS

@Cristy Geçerli bir Ok Fonksiyonu üretimi değil. Nesne içeren bir nesne hazır bilgisi (parantez içine alınmış) oluşturmaya çalıştığınızı düşünüyor ve console.log(...)geçerli bir anahtar adı değil.
thefourtheye

@Cristy: Evet, sanırım yukarıdakilerin yorum kısmı ("Anlam" biti) oldukça doğru olmayabilir, ama şartname kısımları anlatabildiğim kadarıyla. : Aynı zamanda ben V8 aldığım o hatayı uyuyor SyntaxError: Unexpected token ((işaret (de ()sonunda değil (de console.log(...)).
TJ Crowder

@TJCrowder haklısın, hata mesajını değiştirdiğini ve söylemeye çalıştığım şeyin iletilmediğini söyleyeceğim (yani (, yorumlayıcı geçerli bir yorum bulmaya çalıştıktan ve vazgeçtikten sonra yorumlayıcıdan vazgeçmesine neden oldu) "Bu yanlış olmalı o zaman"), bu zaten yanlış olabilir çünkü tercümanın gerçekten nasıl yazıldığını bilmiyorum
Paul S.

Bu konumda geçerli bir jeton olup olmadığını merak ediyorum, yarı kolon eklemeye çalışmaz mıydı?
thefourtheye

2

Bunun gibi sorunları görmenizin nedeni, konsolun kendisinin şu anda hedeflediğiniz bağlamın küresel kapsamını taklit etmeye çalışmasıdır. Ayrıca, konsolda yazdığınız ifadelerden ve ifadelerden gelen dönüş değerlerini yakalamaya çalışır, böylece sonuç olarak görünür. Örneğin şunu ele alalım:

> 3 + 2
< 5

Burada, sanki bir ifademiş gibi çalışır, ama siz bir ifademiş gibi yazmışsınızdır. Normal komut dosyalarında değer atılır, ancak burada kod dahili olarak yönetilmelidir (tüm ifadeyi bir işlev bağlamı ve bir returnifade ile sarmak gibi ), bu da yaşadığınız sorunlar da dahil olmak üzere her türlü garip etkiye neden olur.

Bu, komut dosyalarındaki bazı çıplak ES6 kodunun iyi çalışmasının, ancak Chrome Dev Tools konsolunda çalışmamasının nedenlerinden biridir.

Bunu Düğüm ve Chrome konsolunda yürütmeyi deneyin:

{ let a = 3 }

Düğümde veya bir <script>etikette iyi çalışır, ancak konsolda verir Uncaught SyntaxError: Unexpected identifier. Ayrıca VMxxx:1, değerlendirilen kaynağı incelemek için tıklayabileceğiniz şekilde kaynağa bir bağlantı verir, bu da şu şekilde görünür:

({ let a = 3 })

Peki bunu neden yaptı?

Cevap, sonucun arayana geri dönüp konsolda görüntülenebilmesi için kodunuzu bir ifadeye dönüştürmesi gerektiğidir. Bunu, ifadeyi bir ifade yapan parantez içinde sararak yapabilirsiniz, ancak yukarıdaki bloğu sözdizimsel olarak yanlış yapar (bir ifadenin blok bildirimi olamaz).

Konsol, kod hakkında akıllı olarak bu uç durumları düzeltmeye çalışıyor, ancak bu cevabın kapsamı dışında olduğunu düşünüyorum. Düzeltmeyi düşünecekleri bir şey olup olmadığını görmek için bir hata dosyası gönderebilirsiniz.

Çok benzer bir şeye iyi bir örnek:

https://stackoverflow.com/a/28431346/46588

Kodunuzu çalıştırmanın en güvenli yolu, bir ifade olarak çalıştırılabildiğinden emin olmak SyntaxErrorve gerçek yürütme kodunun ne olduğunu görmek için kaynak bağlantısını incelemek ve bundan bir çözüm tasarlamaktır. Genellikle bir çift stratejik olarak yerleştirilmiş parantez anlamına gelir.

Kısacası: konsol global yürütme bağlamını olabildiğince doğru bir şekilde taklit etmeye çalışır, ancak v8 motoru ve JavaScript semantiği ile etkileşimin sınırlamaları nedeniyle, bazen çözülmesi zor veya imkansızdır.


1
Bütün mesele bu, ben parametre umurumda, ama parametre seti ile çalışmaz.
XCS

Tamam, ne demek istediğini anlıyorum. Aradaki fark, Chrome Geliştirme Araçları konsolunun kodunuzu gerçekten yürütme biçimidir. Cevabı bunu yansıtacak şekilde düzenleyeceğim.
Klemen Slavič

0

Böyle bir soru sordum:

@getify Şu soruyu soruyorum: #IIFE kalıbı üretmek için, bir işlev bildirimi etrafında bir işlev ifadesine dönüştürmek ve sonra çağırmak için parans kullanırız. Şimdi ok işlevi IIFE'lerde, neden paralara ihtiyacımız var ?! Ok işlevi varsayılan olarak zaten bir ifade değil mi ?!

ve bu Kyle Simpson'ın cevabı:

bir ok fonksiyonu olan bir ifade, ama biz son parens ok-Hayatta tüm fonksiyona geçerli çağırmak değil onun vücudunun sadece geçen jetonuyla o, b / c "operatör öncelik" (sorta) çevreleyen parens ihtiyaç .

x => console.log(x)(4)

vs

(x => console.log(x))(4)

- getify (@getify) 12 Haziran 2020


Benim sorum neden bazı derleyiciler üzerinde çalıştığı, diğerlerinde değil.
XCS

Bunun nedeni, farklı derleyicilerin, bazı tarayıcılarda olduğu gibi, elbette farklı derleyicilere sahip olan farklı ayrıntılarda farklı davranmasıdır
Ershad Qaderi

Haklısınız, farklı davranıyorlar, ancak JavaScript özellikleri hepsi için aynı. Hangisinin doğru olduğunu, JS spec'in bu dava hakkında ne söylediğini ve özellikle argüman olmadan çalıştığı ancak argümanla çalışmadığı nasıl olabileceğini merak ettim. Daha teknik bir yanıt arıyordum.
XCS

Örneğiniz oldukça açıktır, ilk durumda gerçekten çağırmalıdır console.log(x)(4).
XCS

Ben sadece burada tahmin ediyorum ama böyle açıklamak çok makul olduğunu düşünüyorum: ok işlev ifadelerinde bir parametre kullanmadığımızda parens kullanmalıyız ve bu motor için bunun bir ok olduğunu çok açık hale getiriyor fonksiyon ifadesi, ancak tek bir parametreniz olduğunda, parenler keyfidir ve bu, bu bir fonksiyonun ve bu motoru karıştırdığı çok açık olmayabilir, karışıklığı gidermek için tüm fonksiyon ifadesinin etrafına bir çift parens koymak zorundayız
Ershad Qaderi
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.