Kendine referans veren anonim kapanmalar: JavaScript eksik mi?


18

Anonim kendi kendine başvuru işlevi kapanmalarının JavaScript'te bu kadar yaygın olması, JavaScript'in eksik bir özellik olduğunu gösteriyor mu? Bunun çoğunu görüyoruz:

(function () { /* do cool stuff */ })();

ve her şeyin bir tat meselesi olduğunu düşünüyorum, ama tek istediğiniz bir özel ad alanı olduğunda bu bir çamur gibi görünmüyor mu? JavaScript paketleri ve uygun sınıfları uygulayamadı mı?

ECMAScript'i temel alan ActionScript 3 ile karşılaştırın

package com.tomauger {
  import bar;
  class Foo {
     public function Foo(){
       // etc...
     }

     public function show(){
       // show stuff
     }

     public function hide(){
       // hide stuff
     }
     // etc...
  }
}

JavaScript'te gerçekleştirdiğimiz kıvrımların aksine (bu, jQuery eklentisi yazma belgelerinden ):

(function( $ ){

  var methods = {
    init : function( options ) { // THIS },
    show : function( ) { // IS   },
    hide : function( ) { // GOOD },
    update : function( content ) { // !!! }
  };

  $.fn.tooltip = function( method ) {

    // Method calling logic
    if ( methods[method] ) {
      return methods[ method ].apply( this, Array.prototype.slice.call( arguments, 1 ));
    } else if ( typeof method === 'object' || ! method ) {
      return methods.init.apply( this, arguments );
    } else {
      $.error( 'Method ' +  method + ' does not exist on jQuery.tooltip' );
    }    

  };

})( jQuery );

Bu sorunun tercihler ve programlama stilleri hakkında kolayca dejenere olabileceğini takdir ediyorum, ancak aslında tecrübeli programcıların bu konuda nasıl hissettiğini ve yeni bir dilin farklı kimliğini öğrenmek gibi doğal olup olmadığını duymak isterim. , henüz uygulanmayan bazı temel programlama dili bileşenlerine geçici bir çözüm gibi mi?


22
"JavaScript ... uygun sınıfları uygulayamadı mı?" Hayır . Zaten uygun prototipleri var. Prototipler sınıflardan daha düşük değildir. Onlar farklı. İnsanlar çeşitli zamanlarda JavaScript'e sınıf eklemeyi denediler ve oldukça başarısız oldular.
Rein Henrichs

5
@Rein: Yine de bir şekilde ActionScript bunu başardı ...
Mason Wheeler

8
@Tom "yerleşik sınıflar" yoktur. Prototip dilde sınıf diye bir şey yoktur . İki paradigmayı karıştırmaya devam ediyorsunuz.
Rein Henrichs

1
Şahsen anonim işlev dili özelliğini sınıflardan daha esnek buluyorum. Ancak bu deyimin yaygın olduğu fonksiyonel programlamayı seviyorum.
dietbuddha

1
Diğerleri için burada: brianodell.net/?page_id=516 prototip dili olarak JavaScript'te harika bir primerdir.
Tom Auger

Yanıtlar:


9

Her şeyin bir tat meselesi olduğunu düşünüyorum, ancak tek istediğiniz bir özel ad alanı olduğunda bu bir çamur gibi görünmüyor mu? JavaScript paketleri ve uygun sınıfları uygulayamadı mı?

Yorumların çoğu, "prototiplerin fakir insanın sınıfları" efsanesine karşıdır, bu yüzden prototip tabanlı OO'nun sınıf tabanlı OO'dan daha düşük olmadığını tekrarlayacağım.

Diğer nokta "özel bir ad alanı istediğiniz zaman bir çamur". Şema'nın kapsamları tanımlamak için tam olarak aynı çamuru kullandığını bilmek sizi şaşırtabilir. Bu, sözcüksel kapsam belirleme işleminin arketipik örneği olmaktan alıkoymadı.

Tabii ki, Şemada, 'çamur' makroların arkasında gizlidir ....


1
Şema'nın, sözcüksel kapsam belirleme işleminin birincil örneği olduğunu veya bunun Şema'nın kapsamları tanımlamak için işlevleri nasıl kullandığıyla ilgili olduğunu iddia etmek için hiçbir kanıt sunmuyorsunuz.
DeadMG

Şema bir suret ancak JS ortak yaratıcısı Brendan Eich burada JS tasarımının bir rol oynayan Düzeni tartışırken bir örnek olmanın Konuşamıyor: readwrite.com/2011/07/22/javascript-was-no-accident
Erik Reppen

7

Öncelikle, birkaç şey:

  1. JavaScript'e bakmanın bir başka yolu, yapı olarak işlevle yapabileceğiniz 1 milyon ve 1 şeydir. Eğer bakarsanız hepsi orada. Hiçbir zaman bir fonksiyondan uzak değildir.

  2. Bu jQuery eklenti yazma şey korkunç. Bunu neden savunduklarını bilmiyorum. $ uzantıları, $ 'ın oldukça iyi kaplanmış değil, tam bir widget oluşturma yöntemlerine sahip olduğu genel kullanım şeyler olmalıdır. Bu bir DOM-API normalleştirme aracıdır. Kullanımı en iyi kendi nesnelerinize gömülüdür. Tam kullanıcı arayüzü kitaplığı deposu olarak kullanmanın cazibesini görmüyorum.

İstemci Tarafı Web'deki paketler Anlamsızdır

Müşteri tarafı web'deki paketler hakkında kişisel olarak sevmediğim şey, aslında gerçekten yapmadığımız bir şeyi yapıyormuş gibi yapıyoruz. Bir .NET web formları ve Java-arkadaşlar dünyamızdan hiçbir zaman pan-out-out-out-out-of-korkunç-şeyler gobs, ben gerçekten ne olduğunu bağlı kaynakları ile HTML bir yığın düşünmek istiyorum ve başka bir şeymiş gibi davranarak yeni şeylere dayanıklı OS uygulama geliştiricilerini yatıştırmaya çalışmayın. İstemci tarafındaki web'deki JS'de, tarayıcı önbelleğe alma bilgisizliği ile çalışan Ajax ile hiçbir şey "ithal" engelleme yapmaz, evet, çoğu yapmaya çalıştı. Tarayıcı için önemli olan tek şey, yüklü ve yorumlanmış olması ya da olmamasıdır. "Her ihtimale karşı" kullanılabilecek bir yerde istemcide daha fazla kod saklanmıyor iyi sebeplerden dolayı. # 1, bir fenomen olarak web uygulamaları için bir eklenti ve tarayıcı eklentisi bağımlılıklarını tanımladığımdan genellikle çok iyi çalışmadı. Şimdi web istiyoruz. Adobe veya Sun bu hafta üçüncü kez güncelleme yapıldıktan sonra değil.

Dil, Yapı İçin İhtiyacı Olan Şeylere Sahiptir

JS nesneleri oldukça değişkendir. Bunu yapmak için yararlı bulduğumuz herhangi bir dereceye kadar isim alanlarının dallanan ağaçlarına sahip olabiliriz ve bunu yapmak çok kolaydır. Ama evet, yeniden kullanılabilir her şey için küresel alanda herhangi bir kütüphanenin kökünü yapıştırmanız gerekir. Tüm bağımlılıklar yine de aynı anda bağlanır ve yüklenir, öyleyse başka bir şey yapmanın anlamı nedir? Küresel ad alanından kaçınmanın amacı, kötü olan herhangi bir şey değildir. Çok fazla şey var, çünkü ad alanı çarpışması riski veya yanlışlıkla temel dil özelliklerinin üzerine yazma riski taşıyorsunuz.

Popüler olması doğru yaptığımız anlamına gelmez

Şimdi bunu bir istemci tarafı web uygulamasında gördüğünüzde:

(function(){
//lots of functions defined and fired and statement code here
})()

Sorun, bir uygulamayı yapılandıracak araçlara sahip olmamamız değil, sorun insanların yapıya değer vermemesi. Bir tasarım ajansında 2-3 sayfalık bir kerelik geçici ıskarta siteleri için bununla ilgili bir sorunum yok. Çirkinleştiği yer, bakımı kolay, okunaklı ve değiştirilmesi kolay bir şey oluşturmanız gerektiğidir.

Ancak, yeniden kullanılabilir tüm nesneleri ve fabrikaları uygulama zamanı geldiğinde ve belki bir veya iki yeni geçici değişken bu sürece girebilirse, bu bir kolaylıktır.

Ancak JS'nin Paketler / Modüller ile Uygulamaları

Bu tür şeylerin çok daha mantıklı olduğu Node.js'de modüllerinin olduğunu unutmayın. JS, diğer dilleri rahatsız eden uber-config-hell'den kaçınabileceğimizi varsayarsak, denklemdeki tek şeydir ve yürütülen her dosya kendi izole kapsamıdır. Ancak bir web sayfasında, bir js dosyasını bağlamak içe aktarma ifadesidir. Daha fazla ithalat yapmak sadece zaman ve kaynak kaybıdır, çünkü kaynakları elde etmek, başka bir sayfanın tekrar gereksinim duyması durumunda bir tarayıcıda önbelleğe alınacaklarını bilmeniz için dosyalara bağlantılar eklemekten çok daha fazla çaba gerektirir. Yani küresel alanda bir nokta işgal ederken jQuery gibi adaptör nesne fabrikaları veya belirli bir alanda büyük bir görev alt kümesini kapsayan daha geleneksel nesneler oluşturmak dışında başka bir şey yaparak küresel alanı bölmeye çalışıyor. Orada'http://wiki.ecmascript.org/doku.php?id=harmony:modules

Bu nedenle hayır, bu tür şeyleri kullanmak için iyi bir neden olduğunda (çoğunlukla yokken) küresel ad alanı kirliliğinden kaçınmak için kullanılan otomatik invokatörlerde yanlış bir şey yoktur. Ve nesnelerimizde kalıcı özel eşdeğer özelliklere sahibiz (sadece yapıcıda bir var tanımlayın ve onu bir özellik olarak göstermeyin).

Ancak, böyle şeyler yapabilmemiz harika. Ağır kullanım, JS geliştiricilerinin hala olgunlaştığının bir işaretidir, ancak burada bir anlam ifade etmeyen istemci tarafı web'de bir paradigma zorlamaya çalışmayan kimseler için dilde bir boşluk yoktur.


Aşağı Seçmene, lütfen nedenini açıklayabilir misiniz? Birisi o kadar çok yazdığında, bir açıklamayı hak ettiğini düşünüyorum!
Songo

+1 iyi cevap, aşağı oy neden önce emin değilim.
pllee

Harika yazma ve harika bir bakış açısı. Ben de "sadece bir kupa doğru olduğu anlamına gelmez" gibi. Benim sorunum, (IMO) geliştirme verimliliğine çeşitli şekillerde yardımcı olan daha sıkı dillerle daha rahat olduğumu düşünüyorum. JavaScript çok fazla yerleşik kontrol ve bakiye ile gerçekten istekli görünüyor: istediğinizi yapabilirsiniz, bu nedenle manzara deyimler ve uygulamaların bir karmaşası var. Kodlama yapınıza yaklaşmanın "doğru" yolunu bulmak zor. Hızlı 1-off meslekler için bu büyük bir endişe değil kabul ediyorum.
Tom Auger

1
IMO, kendinizi asmak dışında bir sürü ip ile yapabileceğiniz birçok şey var ve daha iyi alışkanlıklar geliştirdikçe daha az sıklıkla gerçekleşen zaman zaman kendi kendine askıya alma işlemlerinden daha hızlı sağlam kod yazmayı öğreniyorsunuz, ancak bunun için taklit etmeyeceğim. herkes veya her iş için ideal bir aday. Bununla ilgili ne kadar çok şey öğrenirseniz şüphelenirim, daha fazla tolere edilebilir bulacaksınız. Birinci sınıf işlevler veya JS'ler kadar esnek / değişken nesneler olmadan dillerde şeyler yapmaya çalışırken beynimin yarısını özlüyorum gibi hissediyorum.
Erik Reppen

4

Eksik olan bir diğer şey, javscript'in geriye dönük olarak uyumlu olması gerektiğidir. Paket sözdizimini tanıtmaya çalışırsanız, gerçekten çılgın yollarla web'i kırabilir. Bu kötü olur! Doug Crockford bunu çeşitli noktalarda ve ekleme girişimlerinin neden başarısız olduğunu anlattı.


İyi bir noktaya değindin. Yine de ActionScript bunu yeni bir sürüm ekleyerek yönetti. Komut dosyası etiketinizi tanımlarken, her zaman JavaScript sürümünü belirtebilirsiniz, bu nedenle mevcut siteleri "kırmak" sorun yaratmamalıdır.
Tom Auger

1
Uygulamada, ağdaki komut dosyası etiketlerinin çoğunun sürüm numarası yoktur. Dürüst olmak gerekirse, bu konudaki tüm sorunlardan emin değilim, ama bu şeyleri düşünen insanların bunun yapılabilir olmadığına karar verdiğini biliyorum.
Zachary K

1
@Tom: Adobe ayrıca Flash platformu üzerinde tam denetime sahiptir. Hiç kimse, tüm JS platformları üzerinde tam denetime sahip değildir. Ayrıca, tarayıcıdaki bir JS komut dosyasının sürüm numarasına tıklamak, eski tarayıcıları desteklemediğiniz veya iki komut dosyası yazmanız gerektiği anlamına gelir. Yani, olan bir konudur.
Jeremy Heiler

2

Evet, bir çamur.

Birçok insan "prototiplerin sınıflardan daha düşük olmadığını" söylüyor. Kabul etmiyorum, ama bu bir tercih meselesi. Ancak bu, JavaScript'teki gerçek sorun bile değil - sorun, başlangıçta animasyonlu düğmeler gibi şeyler yapmak için hızlı ve kirli bir komut dosyası dili olarak tasarlanmasıydı. 90'lı yılların ortalarında hiç kimse JavaScript'in şu anda yaptığı çılgın şeylerden bazılarını yapmasının isteneceğini düşünmemişti.


6
Kabul etmiyorum, JavaScript dili gerçekten harika. Altında belirtilen ve karşılıklı olarak uyumsuz bir DOM ile bir araya getirilmiş olması, tüm sorunların başladığı yerdir.
Dean Harding

2
Bunun prototiplerle ne ilgisi var?
Erik Reppen

2

Anonim kendi kendini çağıran işlevler modüller için sınıflardan daha benzerdir. Javascript için varsayılan küresel kapsamda çalıştırmak sinir bozucu. JS.next üzerinde çalışan komite, modül eklemeyi ciddi şekilde düşünüyor, böylece yerel değişkenlerinizi global kapsama bırakmıyorsunuz. Neyse ki, Javascript'in işlevleri, anonim bir işlevi göreceli olarak özel bir kapsam olarak kullanabileceğimiz uygun semantiğe sahiptir.

Sınıfların tartışmaya gerçekten nasıl girdiğini görmüyorum, ancak birçok dilde üst düzey kapsam oluşturma yapısı. Daha iyi bir modül / paket / lütfen-ver-bana-a-yerel-kapsam-so-i-bırak-bırak-değişkenlerimi-global-çevre-yapısına sahip olmak çok güzel olurdu.


1

Ad alanlarını oldukça iyi uygulayabildikleri ExtJS 3 ve 4'e göz atmak isteyebilirsiniz.

- -1'den sonra eklendi

Demek istediğim, tüm bu 'kıvrımları' gizlemek ve hala böyle oldukça kolay kodlara sahip olmak mümkün oldu:

Ext.ns('com.tomauger');
Ext.Loader.load('bar.js'); //unfortunately filname needs to be used
MyNameSpace.Foo = {
   //...
}
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.