Soru JavaScript'te kod organizasyonu etrafında yaygın olarak kabul edilen en iyi uygulamalar [kapalı]


JQuery gibi JavaScript çerçeveleri istemci tarafı web uygulamalarını daha zengin ve daha işlevsel hale getirirken, bir problemi fark etmeye başladım ...

Dünyada bunu nasıl organize ediyorsunuz?

  • Tüm işleyicilerinizi bir noktaya koyun ve tüm etkinlikler için işlevler yazın?
  • Tüm işlevlerinizi sarmak için işlev / sınıflar oluşturun.
  • Deli gibi yaz ve sadece en iyisi için çalışmayı umuyor musun?
  • Vazgeç ve yeni bir kariyer mi aldın?

JQuery'den bahsediyorum, ama genel olarak herhangi bir JavaScript kodu. Çizgiye göre satırlar çizmeye başladığında, senaryo dosyalarını yönetmek veya aradığınızı bulmak zorlaşıyor. Muhtemelen bulduğum en büyük meydan okumalar, aynı şeyi yapmak için pek çok yol var, hangisinin en yaygın olarak kabul edilen en iyi uygulama olduğunu bilmek zor.

Tutmanın en iyi yolu hakkında herhangi bir genel tavsiye var mı? js dosyaları uygulamanızın geri kalanı kadar güzel ve temiz mi? Yoksa bu sadece bir IDE meselesi mi? Orada daha iyi bir seçenek var mı?


DÜZENLE

Bu soru, kod organizasyonu hakkında değil, dosya organizasyonu hakkında daha fazla düşünülmüştür. Dosyaların birleştirilmesi veya içeriğin bölünmesiyle ilgili gerçekten iyi örnekler var.

Sorum şu: gerçek kodunuzu düzenlemek için mevcut yaygın olarak kabul edilen en iyi uygulama yolu nedir? Yolunuz nedir, hatta sayfa öğeleriyle etkileşim kurmanın ve birbirleriyle çakışmayan yeniden kullanılabilir kodlar oluşturmanın önerilen yolu nedir?

Bazı insanlar listeledi ad Bu iyi bir fikir. Diğer bazı yollar nelerdir, özellikle sayfadaki öğelerle ilgilenmek ve kodu düzenli ve düzenli tutmak mı?


537
2017-10-29 15:19


Menşei


kod düzeninin kendisi hakkında konuşmak için zaman alan bir kişi, JS dosyalarını birleştirmek ve sıkıştırmak için hangi aracı kullandığını "değil": stackoverflow.com/questions/16736483/... - Adrien Be


Cevaplar:


Javascript'in ad alanlarının bulunması çok daha hoş olurdu ama Dustin Diaz gibi şeyleri organize etmenin çok iyi olduğunu anladım. İşte bana çok yardımcı olur.

var DED = (function() {

    var private_var;

    function private_method()
    {
        // do stuff here
    }

    return {
        method_1 : function()
            {
                // do stuff here
            },
        method_2 : function()
            {
                // do stuff here
            }
    };
})();

Farklı dosyalarda farklı "ad alanlarını" ve bazen bireysel sınıfları koydum. Genellikle bir dosya ile başlıyorum ve bir sınıf ya da ad alanı olarak bunu garanti etmek için yeterince büyük olur, ben onu kendi dosyasına ayırırım. Tüm dosyaları üretim için birleştirmek için bir araç kullanmak da mükemmel bir fikir.


170



Genelde bunu "crockford yolu" olarak adlandırıyorum. Benden +1 - Matt Briggs
Hatta biraz daha ileri gidebilirsin. Bu bağlantıya bakın: wait-till-i.com/2007/08/22/... - MKroehnert
@MattBriggs aksi taktirde module pattern ve dayanmaktadır IIFE pattern. - Adrien Be
Dersleri bir şekilde ihraç etmene gerek yok mu? Bir nesne böyle bir modülün dışından nasıl yaratılır? Ya da bir yöntem olmalı createNewSomething() dönüş nesnesinde, nesne oluşturma sadece modül içinde gerçekleşir mi? Hm ... Bu sınıfların (yapıcılar) dışarıdan görülebilmesini beklerdim. - robsch


HTML ile herhangi bir javascript dahil etmekten kaçınmaya çalışıyorum. Tüm kod sınıflara kapsüllenmiş ve her sınıf kendi dosyasındadır. Geliştirme için her js dosyasını içerecek ayrı <script> etiketlerim var, ancak HTTP isteklerinin ek yükünü azaltmak için üretim için tek bir büyük pakette birleştiriliyorlar.

Genellikle, her uygulama için tek bir 'ana' js dosyasına sahip olacağım. Yani, bir "anket" uygulaması yazıyorsam, "survey.js" adında bir js dosyası olurdu. Bu giriş noktasını jQuery kodunda içerecektir. Örnekleme sırasında jQuery referansları oluşturup bunları nesnelerimde parametre olarak geçiriyorum. Bu, javascript sınıflarının 'saf' olduğu ve CSS kimlikleri veya sınıf adları için herhangi bir referans içermediği anlamına gelir.

// file: survey.js
$(document).ready(function() {
  var jS = $('#surveycontainer');
  var jB = $('#dimscreencontainer');
  var d = new DimScreen({container: jB});
  var s = new Survey({container: jS, DimScreen: d});
  s.show();
});

Ayrıca okunabilirlik için önemli olması için adlandırma kuralı buluyorum. Örneğin: 'j' tüm jQuery örneklerine ekliyorum.

Yukarıdaki örnekte, DimScreen adlı bir sınıf var. (Ekranın kararmasını ve bir uyarı kutusu açtığını varsayalım.) Ekranı kapsayacak şekilde genişletilebilecek bir div öğesine ihtiyaç duyar ve bir uyarı kutusu ekler, böylece bir jQuery nesnesini geçiririm. jQuery bir eklenti kavramına sahiptir, ancak hiçbir gerçekle karşılaşmadan sınırlayıcı (örneğin, örnekler kalıcı değildir ve erişilemez) gözükmektedir. Dolayısıyla DimScreen sınıfı, jQuery'yi kullanan standart bir javascript sınıfı olacaktır.

// file: dimscreen.js
function DimScreen(opts) { 
   this.jB = opts.container;
   // ...
}; // need the semi-colon for minimizing!


DimScreen.prototype.draw = function(msg) {
  var me = this;
  me.jB.addClass('fullscreen').append('<div>'+msg+'</div>');
  //...
};

Bu yaklaşımı kullanarak bazı oldukça karmaşık başvurular yaptım.


83



Bunu kullanarak buluyorum $ değişken ad öneki daha yaygın bir uygulamadır, ancak yanılıyor olabilirim. Yani, $s = $('...') yerine jS = $('...')sadece bir tercih meselesi sanırım. İlginç olsa da, Macarca notasyonun kod kokusu olduğu düşünülmektedir. Bazı JavaScript kod kuralları / tercihlerimin C # / Java kodlama kurallarına ne kadar farklı olduğu garip. - jamiebarrow
@jamie Bu durumda bir kod kokusu değil, Macar'ın olduğu birkaç durumdan biri. iyi. Okumak isteyebilirsiniz bu. - Dan Abramov
@DanAbramov link için teşekkür ederim. Joel'in tüm bloglarını okumalıyım, o kadar iyi şeyler açıklıyor. Sahip olduğu ün / itibarı kesinlikle hak ediyor. Ben başvurmak Systems Hungarian kod kokusu ve Apps Hungarian Şu andan itibaren bir uygulama olarak :) - jamiebarrow
Sanırım C # dünyasında, aynı zamanda kullanımı teşvik etmek için harika bir makale olabilir. varşimdi bunu düşünüyorum. Kullanmaya karşı argümanların çoğu var döndüğünüzden 'tip' olduğundan emin olamayacağınız yer, ama sanırım argüman, ne döndüğünün 'sınıfını' bilmemekle ilgilidir. Apps Macarca kullanıyorsanız, o endişeye sahip olmamanız gerekir ... ilginç. - jamiebarrow
@Marnen: Ben senin noktanı görüyorum, ama programcı için bir rehber olarak işe yaramaz. $ Öneki, daha sonra kodumu okurken ne olduğunu hatırlatır ve böylece daha hızlı bir anlamaya yardımcı olur. - Sean


Komut dosyalarınızı geliştirme için ayrı dosyalara bölebilirsiniz, ardından hepsini bir araya getirdiğiniz ve çalıştırdığınız bir "yayın" sürümü oluşturun. YUI Kompresör ya da benzer bir şey.


37



Bazen gereksiz javascript betikleri vardır. Bunları müşteriye göndermek israftır. Sadece ihtiyaç duyulan şeyi göndermek için bir şey olduğunu düşünüyorum. Elbette, intranet uygulaması gibi tüm gün boyunca kullanılan bir web uygulaması için, ilk sayfa yüklemesinde tüm partiyi bir kerede göndermeniz daha iyi olabilir. - DOK
@ DOK derleme kullanılmayan şeylerin eksizyonu içermelidir. - aehlke
Ayrıca, ilk sayfayı yüklediğiniz ve daha sonra gerekli komut dosyalarının eşzamansız yüklenmesini gerçekleştiren (bu sorunun diğer yanıtlarında da belirtildiği gibi) bant genişliği gereksinimlerini denemek ve azaltmak için bir tembel yükleme konsepti de vardır. Yine de, bu daha fazla istek gerektirebilir ve aslında daha az kullanılabilir. @DOK, JS önbelleğe alınmışsa, bir orta talep birkaç küçük olandan daha iyi olabilir. - jamiebarrow


Daha önceki yazılardan esinlenerek bir kopyasını yaptım Rakefile ve satıcı dizinleri dağıtıldı WysiHat (changelog tarafından belirtilen bir RTE) ve kod kontrolünü dahil etmek için birkaç değişiklik yaptı JSLint ve minification ile YUI Kompresör.

Fikir kullanmak Çarklar (WysiHat'tan), birden fazla JavaScripts'i bir dosyaya birleştirmek için, birleştirilmiş dosyanın JSLint ile sözdizimini kontrol edin ve dağıtmadan önce YUI Kompresörü ile küçültün.

Ön şartlar

  • Java Runtime
  • yakut ve tırmık
  • Bir JAR'ın nasıl yerleştirileceğini bilmelisin Sınıf yolu

Şimdi yap

  1. İndir Gergedan ve JAR ("js.jar") sınıf yoluna koy
  2. İndir YUI Kompresör ve JAR (build / yuicompressor-xyz.jar) sınıf yolunuza koydu
  3. İndir WysiHat ve "satıcı" dizinini JavaScript projenizin köküne kopyalayın
  4. İndir Rhino için JSLint ve "satıcı" dizininin içine koy

Şimdi JavaScript projesinin kök dizininde "Rakefile" adlı bir dosya oluşturun ve aşağıdaki içeriği ekleyin:

require 'rake'

ROOT            = File.expand_path(File.dirname(__FILE__))
OUTPUT_MERGED   = "final.js"
OUTPUT_MINIFIED = "final.min.js"

task :default => :check

desc "Merges the JavaScript sources."
task :merge do
  require File.join(ROOT, "vendor", "sprockets")

  environment  = Sprockets::Environment.new(".")
  preprocessor = Sprockets::Preprocessor.new(environment)

  %w(main.js).each do |filename|
    pathname = environment.find(filename)
    preprocessor.require(pathname.source_file)
  end

  output = preprocessor.output_file
  File.open(File.join(ROOT, OUTPUT_MERGED), 'w') { |f| f.write(output) }
end

desc "Check the JavaScript source with JSLint."
task :check => [:merge] do
  jslint_path = File.join(ROOT, "vendor", "jslint.js")

  sh 'java', 'org.mozilla.javascript.tools.shell.Main',
    jslint_path, OUTPUT_MERGED
end

desc "Minifies the JavaScript source."
task :minify => [:merge] do
  sh 'java', 'com.yahoo.platform.yui.compressor.Bootstrap', '-v',
    OUTPUT_MERGED, '-o', OUTPUT_MINIFIED
end

Her şeyi doğru bir şekilde yaparsanız, konsolunuzda aşağıdaki komutları kullanabilmeniz gerekir:

  • rake merge - farklı JavaScript dosyalarını bir araya getirmek
  • rake check - kodunuzun sözdizimini kontrol etmek için (bu varsayılan görev, böylece sadece yazabilirsiniz rake)
  • rake minify - JS kodunuzun küçültülmüş sürümünü hazırlamak için

Kaynak birleştirmede

Sprockets kullanarak, JavaScript ön-işlemcisi ekleyebilirsiniz (veya require) diğer JavaScript dosyaları. İlk dosyadan diğer komut dosyalarını eklemek için aşağıdaki sözdizimini kullanın ("main.js" olarak adlandırılır, ancak bunu Rakefile'de değiştirebilirsiniz):

(function() {
//= require "subdir/jsfile.js"
//= require "anotherfile.js"

    // some code that depends on included files
    // note that all included files can be in the same private scope
})();

Ve sonra...

Otomatik ünite testini ayarlamak için WysiHat ile birlikte verilen Rakefile'ye bir göz atın. Güzel iş :)

Ve şimdi cevap için

Bu orijinal soruyu çok iyi cevaplamıyor. Biliyorum ve bunun için üzgünüm, ama burada yayınladım çünkü umarım birileri için karışıklıklarını organize etmek yararlı olabilir.

Benim problemime yaklaşımım, nesne tabanlı modelleme yapmak ve uygulamaları farklı dosyalara ayırabilmektir. Daha sonra, işleyiciler mümkün olduğunca kısa olmalıdır. İle örnek Listsingleton da güzel biri.

Ve ad alanları ... onlar daha derin nesne yapısıyla taklit edilebilirler.

if (typeof org === 'undefined') {
    var org = {};
}

if (!org.hasOwnProperty('example')) {
    org.example = {};
}

org.example.AnotherObject = function () {
    // constructor body
};

Ben imitasyonların büyük bir hayranı değilim, ancak küresel kapsam dışına taşımak istediğiniz birçok nesneye sahipseniz bu yardımcı olabilir.


26





Kod organizasyonu, sözleşmelerin ve belgelendirme standartlarının kabul edilmesini gerektirir:
1. Bir fiziksel dosya için ad alanı kodu;

Exc = {};


2. Bu sınıftaki javascript grup sınıfları;
3. Gerçek dünyadaki nesneleri temsil etmek için Prototipler veya ilgili işlevler veya sınıflar ayarlayın;


Exc = {};
Exc.ui = {};
Exc.ui.maskedInput = function (mask) {
    this.mask = mask;
    ...
};
Exc.ui.domTips = function (dom, tips) {
    this.dom = gift;
    this.tips = tips;
    ...
};


4. Kodu geliştirmek için kuralları ayarlayın. Örneğin, tüm dahili işlevlerini veya yöntemlerini nesne türünün sınıf özniteliğinde gruplandırın.

Exc.ui.domTips = function (dom, tips) {
    this.dom = gift;
    this.tips = tips;
    this.internal = {
        widthEstimates: function (tips) {
            ...
        }
        formatTips: function () {
            ...
        }
    };
    ...
};


5. İsim alanlarını, sınıfları, yöntemleri ve değişkenleri belgelendirin. Gerekli olduğunda, bazı kodlar da tartışılır (bazı FI'ler ve Forlar, genellikle kodun önemli mantığını uygularlar).

/**
  * Namespace <i> Example </i> created to group other namespaces of the "Example".  
  */
Exc = {};
/**
  * Namespace <i> ui </i> created with the aim of grouping namespaces user interface.
  */
Exc.ui = {};

/**
  * Class <i> maskdInput </i> used to add an input HTML formatting capabilities and validation of data and information.
  * @ Param {String} mask - mask validation of input data.
  */
Exc.ui.maskedInput = function (mask) {
    this.mask = mask;
    ...
};

/**
  * Class <i> domTips </i> used to add an HTML element the ability to present tips and information about its function or rule input etc..
  * @ Param {String} id - id of the HTML element.
  * @ Param {String} tips - tips on the element that will appear when the mouse is over the element whose identifier is id <i> </i>.
  */
  Exc.ui.domTips = function (id, tips) {
    this.domID = id;
    this.tips = tips;
    ...
};


Bunlar sadece bazı ipuçları, ancak bu kodun düzenlenmesinde çok yardımcı oldu. Başarılı olmak için disiplininizin olması gerektiğini unutmayın!


18





İyi OO tasarım prensiplerini ve tasarım kalıplarını takip etmek, kodunuzun bakımını ve anlaşılmasını kolaylaştırmak için uzun bir yol kat eder. Ancak son zamanlarda keşfettiğim en iyi şeylerden biri, yayınlama / abone olma konusunda sinyaller ve yuvalardır. Bir bak bakalım http://markdotmeyer.blogspot.com/2008/09/jquery-publish-subscribe.html Basit bir jQuery uygulaması için.

Fikir, GUI geliştirme için diğer dillerde iyi kullanılır. Kodunuzda önemli bir şey olduğunda, diğer nesnelerdeki diğer yöntemlerin abone olabileceği global bir sentetik olay yayınlarsınız. Bu, nesnelerin mükemmel bir şekilde ayrılmasını sağlar.

Bence Dojo (ve Prototip?) Bu tekniğin yerleşik bir versiyonuna sahip.

Ayrıca bakınız Sinyaller ve yuvalar nelerdir?


13



Bunu jQuery'de yaptım. JS'nin yerleşik bir olay modeli vardır, bu yüzden çok fazla çerçeve desteğine ihtiyacınız yoktur. - Marnen Laibow-Koser


Başarıyla uygulayabildim Javascript Modülü Kalıbı önceki işimde bir Ext JS uygulamasına. Güzel kapsüllü kod oluşturmak için basit bir yol sağladı.


12





Dojo, birinci güne ait modül sistemini aldı. Aslında, Dojo'nun köşe taşı olduğu düşünülüyor.

Dojo modülleri kullanılarak aşağıdaki hedefler elde edilir:

  • Dojo kodu ve özel kod için ad alanlarıdojo.declare()) - küresel alanı kirletmeyin, diğer kütüphanelerle birlikte bulunmayın ve kullanıcının Dojo'ya duyarlı olmayan kodu.
  • Modülleri eşzamanlı olarak veya eşzamansız olarak ad yüklemedojo.require()).
  • Özel, yalnızca web uygulamanızın gereksinimlerini içermek üzere tek bir dosya veya birbirine bağlı dosyalar grubunu (katman olarak adlandırılır) oluşturmak için modül bağımlılıklarını analiz ederek oluşturulur. Özel yapılar, Dojo modülleri ve müşteri tarafından sağlanan modülleri de içerebilir.
  • Dojo ve kullanıcı koduna şeffaf CDN tabanlı erişim. Hem AOL hem de Google Dojo'yu bu şekilde taşıyorlar, ancak bazı müşteriler özel web uygulamaları için de bunu yapıyor.

11





Çıkış yapmak JavasciptMVC.

Yapabilirsin :

  • kodunuzu modele ayırın, katmanları görüntüleyin ve denetleyin.

  • tüm kodu tek bir üretim dosyasına sıkıştır

  • otomatik kod oluştur

  • birim testleri oluştur ve çalıştır

  • ve daha fazlası ...

Hepsinden iyisi, jQuery'yi kullanır, böylece diğer jQuery eklentilerinden de yararlanabilirsiniz.


9



Evet, jmvc kullandım ve oldukça iyi - belgeler daha iyi olsa da - meouw