JavaScript에서 코드 구성과 관련하여 일반적으로 인정되는 모범 사례 [닫기]


561

jQuery와 같은 JavaScript 프레임 워크가 클라이언트 측 웹 애플리케이션을 더욱 풍부하고 기능적으로 만들면서 한 가지 문제점을 발견하기 시작했습니다.

이 세상을 어떻게 조직적으로 유지합니까?

  • 모든 핸들러를 한 곳에 배치하고 모든 이벤트에 대한 함수를 작성 하시겠습니까?
  • 모든 기능을 래핑하는 함수 / 클래스를 만드시겠습니까?
  • 미친 것처럼 쓰고 그것이 최선을 다하기를 바랍니다.
  • 포기하고 새로운 경력을 쌓으세요?

jQuery를 언급했지만 실제로는 일반적인 JavaScript 코드입니다. 줄 위의 줄이 쌓이기 시작하면 스크립트 파일을 관리하거나 찾고있는 것을 찾는 것이 더 어려워집니다. 내가 찾은 가장 큰 문제는 아마도 똑같은 일을 할 수있는 방법이 너무 많다는 것입니다.

.js 파일을 나머지 응용 프로그램처럼 멋지고 깔끔하게 유지하는 가장 좋은 방법에 대한 일반적인 권장 사항이 있습니까? 아니면 이것은 IDE의 문제입니까? 더 나은 옵션이 있습니까?


편집하다

이 질문은 파일 구성이 아니라 코드 구성에 관한 것입니다. 파일을 병합하거나 콘텐츠를 분할하는 몇 가지 좋은 예가 있습니다.

내 질문은 : 실제 코드를 구성하는 현재 일반적으로 허용되는 모범 사례 방법은 무엇입니까? 페이지 요소와 상호 작용하고 서로 충돌하지 않는 재사용 가능한 코드를 만드는 방법은 무엇입니까?

일부 사람들은 네임 스페이스 를 나열 했으며 이는 좋은 생각입니다. 페이지의 요소를보다 구체적으로 다루고 코드를 정리하고 깔끔하게 유지하는 다른 방법은 무엇입니까?


JS 파일을 연결하고 압축하는 데 사용하는 도구가 아니라 "코드 구성"자체에 대해 실제로 시간을 투자 한 사람 : stackoverflow.com/questions/16736483/…
Adrien Be

답변:


183

자바 스크립트에 네임 스페이스가 내장되어 있으면 훨씬 좋을 것입니다. 그러나 Dustin Diaz와 같은 것을 조직 하면 여기 에 많은 도움이됩니다.

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

다른 "네임 스페이스"와 때로는 개별 클래스를 별도의 파일에 넣었습니다. 일반적으로 하나의 파일로 시작하고 클래스 또는 네임 스페이스가 그것을 보증 할만 큼 커지면 자체 파일로 분리합니다. 제작을 위해 모든 파일을 결합하는 도구를 사용하는 것도 훌륭한 아이디어입니다.


24
나는 보통 그것을 "고치기 길"이라고 부릅니다. +1
Matt Briggs 1

4
조금 더 나아가도됩니다. 이 링크를 참조하십시오 : wait-till-i.com/2007/08/22/…
MKroehnert

4
@MattBriggs는 그렇지 않으면를 호출하며 module pattern를 기반으로합니다 IIFE pattern.
Adrien Be

어떻게 든 클래스를 내보낼 필요가 없습니까? 그러한 모듈 외부에서 객체가 어떻게 생성됩니까? 또는 createNewSomething()반환 객체에 메서드 가 있어야 모듈 내에서만 객체 생성이 발생합니까? 흠 ... 나는 클래스 (생성자)가 외부에서 보이기를 기대합니다.
robsch

@robsch 그의 예제는 매개 변수를 사용하지 않지만 대부분을 수행합니다. 이 일반적으로 수행하는 방법을 여기 내 예를 참조 (타이프 라이터, 그러나 99 % 동일) : repl.it/@fatso83/Module-Pattern-in-TypeScript
oligofren

88

HTML에 자바 스크립트를 포함시키지 마십시오. 모든 코드는 클래스로 캡슐화되며 각 클래스는 자체 파일에 있습니다. 개발을 위해 각 js 파일을 포함하는 별도의 <script> 태그가 있지만 HTTP 요청의 오버 헤드를 줄이기 위해 프로덕션을 위해 하나의 큰 패키지로 병합됩니다.

일반적으로 각 응용 프로그램마다 하나의 'main'js 파일이 있습니다. 따라서 "survey"응용 프로그램을 작성하는 경우 "survey.js"라는 js 파일이 있습니다. 여기에는 jQuery 코드의 진입 점이 포함됩니다. 인스턴스화 중에 jQuery 참조를 작성한 다음이를 매개 변수로 오브젝트에 전달합니다. 이것은 자바 스크립트 클래스가 '순수'하며 CSS ID 또는 클래스 이름에 대한 참조를 포함하지 않음을 의미합니다.

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

또한 명명 규칙이 가독성에 중요하다는 것을 알았습니다. 예를 들어 : 모든 jQuery 인스턴스 앞에 'j'를 추가합니다.

위 예제에는 DimScreen이라는 클래스가 있습니다. (이것은 화면을 어둡게하고 경고 상자를 팝업한다고 가정합니다.) 화면을 덮기 위해 확대하고 경고 상자를 추가 할 수있는 div 요소가 필요하므로 jQuery 객체를 전달합니다. jQuery는 플러그인 개념을 가지고 있지만 실제 거꾸로하지 않고 제한적인 것처럼 보입니다 (예 : 인스턴스가 영구적이지 않고 액세스 할 수 없음). DimScreen 클래스는 jQuery를 사용하는 표준 자바 스크립트 클래스입니다.

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

이 접근법을 사용하여 상당히 복잡한 응용 프로그램을 만들었습니다.


15
내가 사용하는 것을 발견 $변수 이름을 접두어로하는 것이 더 일반적이다, 그러나 나는 틀릴 수 있었다. 따라서, $s = $('...')대신 jS = $('...')선호도의 문제라고 생각합니다. 헝가리어 표기법이 코드 냄새라고 생각되기 때문에 흥미 롭습니다. 내 JavaScript 코드 규칙 / 기본 설정이 C # / Java 코딩 규칙과 다른 점이 이상합니다.
jamiebarrow

9
@jamie이 경우 코드 냄새가 아니며 헝가리어가 좋은 몇 안되는 경우 중 하나입니다 . 당신은 이것을 읽을 수 있습니다 .
Dan Abramov

3
@DanAbramov 링크 주셔서 감사합니다. 나는 정말로 Joel의 모든 블로그를 읽어야합니다. 그가 가진 명성 / 명성을 분명히받을 자격이 있습니다. 나는 Systems Hungarian코드 냄새와 Apps Hungarian지금부터 연습 으로 언급 할 것이다 :)
jamiebarrow

나는 C # 세계에서,의 사용을 장려하는 훌륭한 기사 일 수 var있다고 생각합니다. 사용에 대한 대부분의 주장 var은 반환 된 것의 '유형'을 확신 할 수없는 곳이지만, 인수는 반환 된 것의 '클래스'를 모르는 것에 반대해야한다고 생각합니다. Apps Hungarian을 사용하는 경우 관심을 가져서는 안됩니다 ... 흥미 롭습니다.
jamiebarrow

3
@Marnen : 요점을 알지만 프로그래머를위한 안내 서로는 쓸모가 없습니다. $ 접두어는 나중에 내 코드를 읽을 때 그 내용을 알려주므로 더 빨리 이해할 수 있습니다.
Sean

39

개발을 위해 스크립트를 별도의 파일로 나눈 다음 "릴리스"버전을 만들어서 모두 함께 크래킹하고 YUI 압축기 또는 이와 유사한 것을 실행할 수 있습니다.


때로는 불필요한 자바 스크립트 스크립트가 있습니다. 그것들을 클라이언트에게 보내는 것은 낭비입니다. 필요한 것만 보내면된다고 생각합니다. 물론 인트라넷 앱과 같이 하루 종일 사용되는 웹 앱의 경우 첫 번째 페이지로드시 전체 일괄 처리를 한 번에 보내는 것이 좋습니다.
DOK

2
@DOK 컴파일에는 사용하지 않는 것들의 절제가 포함되어야합니다.
aehlke

또한 초기 페이지를로드 한 다음 필요한 스크립트 파일의 비동기로드를 수행하는 대역폭 요구를 시도 및 감소시키기위한 지연로드 개념이 있습니다 (이 질문에 대한 다른 답변에서 언급 한 바와 같이). 그러나 더 많은 요청이 필요할 수 있으며 실제로는 덜 유용 할 수 있습니다. @DOK, JS가 캐시되면 하나의 중간 요청이 몇 개의 작은 요청보다 낫습니다.
jamiebarrow

27

이전 게시물에서 영감을 받아 WysiHat (changelog에서 언급 한 RTE)과 함께 배포 된 Rakefile공급 업체 디렉토리 의 사본을 만들고 JSLint를 사용한 코드 검사 및 YUI Compressor로 축소 를 포함하도록 약간 수정했습니다 .

아이디어는 WysiHat의 Sprockets 를 사용 하여 여러 JavaScript를 하나의 파일로 병합하고 병합 된 파일의 구문을 JSLint로 확인한 후 배포 전에 YUI Compressor로 최소화하는 것입니다.

전제 조건

  • 자바 런타임
  • 루비와 갈퀴 보석
  • JAR을 클래스 경로 에 넣는 방법을 알아야합니다

이제 해

  1. Rhino를 다운로드 하고 JAR ( "js.jar")을 클래스 경로에 넣으십시오.
  2. YUI Compressor를 다운로드 하고 JAR (build / yuicompressor-xyz.jar)을 클래스 경로에 넣으십시오.
  3. WysiHat을 다운로드 하고 "공급 업체"디렉토리를 JavaScript 프로젝트의 루트에 복사하십시오.
  4. Rhino 용 JSLint를 다운로드 하여 "공급 업체"디렉토리에 넣습니다.

이제 JavaScript 프로젝트의 루트 디렉토리에 "Rakefile"이라는 파일을 작성하고 다음 컨텐츠를 추가하십시오.

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

모든 것을 올바르게 수행했다면 콘솔에서 다음 명령을 사용할 수 있어야합니다.

  • rake merge -다른 JavaScript 파일을 하나로 병합
  • rake check-코드 구문을 확인하려면 (이것이 기본 작업이므로 간단히 입력 할 수 있습니다 rake)
  • rake minify -JS 코드의 축소 버전을 준비

소스 병합

Sprockets를 사용하면 JavaScript 전 처리기에서 require다른 JavaScript 파일을 포함 (또는 ) 할 수 있습니다. 다음 구문을 사용하여 초기 파일 ( "main.js"라는 다른 스크립트를 포함하지만 Rakefile에서 변경할 수 있음) :

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

그리고...

자동 단위 테스트를 설정하려면 WysiHat과 함께 제공된 Rakefile을 살펴보십시오. 좋은 물건 :)

그리고 지금 답을 위해

이것은 원래의 질문에 잘 대답하지 못합니다. 나는 그것을 알고 미안하지만, 나는 그것을 다른 사람이 그들의 혼란을 조직하는 데 유용 할 수 있기를 바랍니다.

문제에 대한 나의 접근 방식은 가능한 많은 객체 지향 모델링을 수행하고 구현을 다른 파일로 분리하는 것입니다. 그런 다음 처리기는 가능한 짧아야합니다. List싱글 톤을 사용한 예제 도 좋습니다.

그리고 네임 스페이스는 ... 더 깊은 객체 구조로 모방 될 수 있습니다.

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

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

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

나는 모방을 좋아하지는 않지만 전역 범위를 벗어나고 싶은 많은 객체가있는 경우 도움이 될 수 있습니다.


18

코드 구성에는 규칙 및 문서 표준을 채택해야합니다.
1. 실제 파일의 네임 스페이스 코드;

Exc = {};


2.이 네임 스페이스에서 클래스를 자바 스크립트로 묶습니다.
3. 실제 객체를 나타내는 프로토 타입 또는 관련 함수 또는 클래스를 설정합니다.

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


4. 코드를 개선하기위한 규칙을 설정하십시오. 예를 들어, 모든 내부 함수 또는 메소드를 오브젝트 유형의 클래스 속성으로 그룹화하십시오.

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


5. 네임 스페이스, 클래스, 메소드 및 변수를 문서화하십시오. 필요한 경우 일부 코드 (일부 FI 및 Fors)는 일반적으로 코드의 중요한 논리를 구현합니다.

/**
  * 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;
    ...
};


이것들은 몇 가지 팁이지만 코드 구성에 크게 도움이되었습니다. 성공하려면 훈련이 있어야합니다!


13

좋은 OO 디자인 원칙과 디자인 패턴을 따르면 코드를 쉽게 유지 관리하고 이해하는 데 많은 도움이됩니다. 그러나 최근에 내가 발견 한 가장 좋은 것 중 하나는 발행 / 구독이라고하는 신호와 슬롯입니다. 한 번 봐 가지고 http://markdotmeyer.blogspot.com/2008/09/jquery-publish-subscribe.html 간단한 jQuery를 구현합니다.

이 아이디어는 GUI 개발을 위해 다른 언어로 잘 사용됩니다. 코드 어딘가에 중요한 일이 발생하면 다른 객체의 다른 메소드가 구독 할 수있는 전역 합성 이벤트를 게시합니다. 이것은 객체의 탁월한 분리를 제공합니다.

Dojo (및 프로토 타입?)에는이 기술의 기본 제공 버전이 있다고 생각합니다.

또한 참조 신호와 슬롯은 무엇입니까?


jQuery 에서이 작업을 수행했습니다. JS에는 이벤트 모델이 내장되어 있으므로 프레임 워크를 많이 지원할 필요가 없습니다.
Marnen Laibow-Koser

12

이전 작업에서 Javascript 모듈 패턴 을 Ext JS 응용 프로그램에 성공적으로 적용 할 수있었습니다 . 멋지게 캡슐화 된 코드를 만드는 간단한 방법을 제공했습니다.


11

Dojo는 처음부터 모듈 시스템을 가지고있었습니다. 실제로 그것은 Dojo의 초석으로 간주됩니다.

Dojo 모듈을 사용하면 다음과 같은 목표를 달성 할 수 있습니다.

  • Dojo 코드 및 사용자 정의 코드 ( dojo.declare())의 네임 스페이스 — 글로벌 공간을 오염시키지 않고 다른 라이브러리와 공존하지 않으며 사용자의 Dojo를 인식하지 않는 코드입니다.
  • 이름 ( dojo.require())으로 동기식 또는 비동기식으로 모듈로드
  • 웹 응용 프로그램에 필요한 것만 포함하도록 단일 파일 또는 상호 의존적 파일 그룹 (소위 계층)을 만들기 위해 모듈 종속성을 분석하여 사용자 지정 빌드 사용자 정의 빌드에는 Dojo 모듈 및 고객 제공 모듈도 포함될 수 있습니다.
  • Dojo 및 사용자 코드에 대한 투명한 CDN 기반 액세스. AOL과 구글 모두이 방식으로 도장을 가지고 있지만, 일부 고객들은 사용자 정의 웹 응용 프로그램에 대해 그렇게 할뿐만 아니라.

9

JavasciptMVC를 확인하십시오 .

당신은 할 수 있습니다 :

  • 코드를 모델, 뷰 및 컨트롤러 계층으로 나눕니다.

  • 모든 코드를 단일 프로덕션 파일로 압축

  • 자동 생성 코드

  • 단위 테스트 작성 및 실행

  • 그리고 더 많은 ...

무엇보다도, jQuery를 사용하므로 다른 jQuery 플러그인도 활용할 수 있습니다.


예, jmvc를 사용했는데 꽤 좋습니다. 문서가 더 나을 수도 있습니다.
meouw

9

상사는 여전히 모듈 식 코드 (C 언어)를 작성할 때에 대해 이야기하고 있으며 오늘날 코드가 얼마나 엉터리인지 불평합니다! 프로그래머는 모든 프레임 워크에서 어셈블리를 작성할 수 있다고합니다. 코드 구성을 극복하기위한 전략이 항상 있습니다. 기본적인 문제는 자바 스크립트를 장난감으로 취급하고 배우려고 시도하지 않는 사람들입니다.

필자의 경우 적절한 init_screen ()을 사용하여 UI 테마 또는 응용 프로그램 화면을 기준으로 js 파일을 작성합니다. 적절한 ID 명명 규칙을 사용하여 루트 요소 수준에서 네임 스페이스 충돌이 없는지 확인합니다. 눈에 잘 띄지 않는 window.load ()에서 최상위 ID를 기반으로 항목을 묶습니다.

모든 개인 메소드를 숨기려면 Java 스크립트 클로저와 패턴을 엄격하게 사용합니다. 이렇게 한 후에 속성 / 함수 정의 / 변수 정의가 충돌하는 문제에 직면하지 않았습니다. 그러나 팀과 함께 일할 때 종종 동일한 엄격함을 시행하기가 어렵습니다.


9

MVC 프레임 워크를 언급 한 사람이 아무도 없습니다. Backbone.js 를 사용하여 코드를 모듈화하고 분리했으며, 그 가치는 매우 높습니다.

이러한 종류의 프레임 워크는 꽤 많으며 대부분도 매우 작습니다. 내 개인적인 견해는 화려한 UI를 위해 두 줄 이상의 jQuery를 작성하거나 풍부한 Ajax 애플리케이션을 원한다면 MVC 프레임 워크가 삶을 훨씬 쉽게 만들 수 있다는 것입니다.


8

"미친 것처럼 쓰고 최선을 다하길 바래?"나는 자바 스크립트 코드가 많은 거대한 응용 프로그램 인 2 명의 개발자 만 개발하고 유지 관리하는 프로젝트를 보았습니다. 그 외에도 생각할 수있는 모든 jquery 함수에 대한 다른 바로 가기가있었습니다. 클래스, 모듈, 네임 스페이스 및 전체 우주와 동등한 jquery이므로 코드를 플러그인으로 구성하는 것이 좋습니다. 그러나 상황이 훨씬 나빠 졌으므로 이제는 프로젝트에서 사용되는 3 줄의 코드 조합을 대체하는 플러그인을 작성하기 시작했습니다. 개성 나는 jQuery가 악마라고 생각하며 많은 자바 스크립트가있는 프로젝트에서 사용해서는 안됩니다. 왜냐하면 게으르고 코드를 구성하는 것을 생각하지 않기 때문입니다. 40 개의 체인 jQuery 함수가있는 한 줄보다 100 줄의 자바 스크립트를 읽는 것이 좋습니다. 농담이 아닙니다). 일반적인 믿음과는 달리, 네임 스페이스 및 클래스와 동등한 자바 스크립트 코드를 구성하는 것은 매우 쉽습니다. 그것이 YUI와 Dojo가하는 일입니다. 원하는 경우 쉽게 자신을 굴릴 수 있습니다. YUI의 접근 방식이 훨씬 더 좋고 효율적이라는 것을 알았습니다. 그러나 일반적으로 유용한 것을 작성하려면 YUI 명명 규칙을 보완하기 위해 스 니펫을 지원하는 멋진 편집기가 필요합니다.


3
정말 긴 체인 명령에 대해서는 동의하지만 jQuery의 가장 중요한 부분 중 하나는 HTML에서 모든 Javascript를 유지한다는 것입니다. 요소에 ID 또는 <whatever> 이벤트를 추가하기 위해 "바늘"없이 모든 요소에 대한 이벤트 핸들러를 설정할 수 있습니다. 항상 그렇듯이 어떤 도구를 과도하게 사용하는 것은 좋지 않습니다 ...
Hugoware

jQuery에서 잘 조직 된 거대한 프로젝트를 작업했습니다. 왜 당신이 조직에 방해가된다고 생각하는지 모르겠습니다.
Marnen Laibow-Koser

7

화면에서 여러 번 인스턴스화 할 필요가없는 모든 것, 다른 모든 클래스에 대해 단일 톤을 만듭니다. 그리고 그것들은 모두 같은 파일에서 같은 네임 스페이스에 저장됩니다. 모든 것은 주석을 달고 UML 상태 다이어그램으로 설계되었습니다. 자바 스크립트 코드는 HTML이 없으므로 인라인 자바 스크립트가 없으며 jquery를 사용하여 크로스 브라우저 문제를 최소화하는 경향이 있습니다.


3
좋은 의견은 KEY입니다-당신이 말하지 않아서 기쁘다. 일관된 이름 지정 규칙, 변수 & amp; 함수, 그리고 언급했듯이 클래스 대 싱글 톤의 신중한 사용.
matt lohkamp

아니오. 주석이 필요한 경우 일반적으로 코드를 충분히 읽을 수 없습니다. 주석이 필요없는 코드를 작성하려고 노력하십시오.
Marnen Laibow-Koser 3

또한 UML 및 상태 다이어그램이 필요한 경우 코드에서 아키텍처가 충분히 명확하지 않을 수 있습니다. 다운 보팅.
Marnen Laibow-Koser

1
@Marnen 잘 작성된 프로젝트에는 WHAT가 아닌 WHY를 설명하는 주석이 포함됩니다. 이 코드는 이미 WHAT를 설명하지만 종종 WHY를 설명하는 것이 필요합니다. 공감.
Cypher

@Cypher 잘 작성된 프로젝트는 일반적으로 "무엇"이 아니라 "왜"를 말할 수있는 충분한 코드를 가지고 있습니다. 나는 그것이 왜 코드와 동기화되어 있다는 것을 보증하지 않기 때문에 "왜"라고 말하는 의견을 믿지 않을 것입니다. 코드 자체를 문서화하십시오.
Marnen Laibow-Koser

6

마지막 프로젝트 -Viajeros.com-에서 여러 기술을 조합하여 사용했습니다. 웹 응용 프로그램을 구성하는 방법을 모르겠습니다. Viajeros는 잘 정의 된 섹션이있는 여행자를위한 소셜 네트워킹 사이트이므로 각 지역의 코드를 쉽게 분리 할 수 ​​있습니다.

사이트 섹션에 따라 네임 스페이스 시뮬레이션과 모듈의 지연로드를 사용합니다. 각 페이지로드에서 나는 "vjr"객체를 선언하고 항상 공통 함수 세트를로드합니다 (vjr.base.js). 그런 다음 각 HTML 페이지는 간단한 모듈로 필요한 모듈을 결정합니다.

vjr.Required = ["vjr.gallery", "vjr.comments", "vjr.favorites"];

Vjr.base.js는 서버에서 각각 하나를 가져 와서 실행합니다.

vjr.include(vjr.Required);
vjr.include = function(moduleList) {
  if (!moduleList) return false;
  for (var i = 0; i < moduleList.length; i++) {
    if (moduleList[i]) {
      $.ajax({
        type: "GET", url: vjr.module2fileName(moduleList[i]), dataType: "script"
      });
    }
  }
};

모든 "모듈"의 구조는 다음과 같습니다.

vjr.comments = {}

vjr.comments.submitComment = function() { // do stuff }
vjr.comments.validateComment = function() { // do stuff }

// Handlers
vjr.comments.setUpUI = function() {
    // Assign handlers to screen elements
}

vjr.comments.init = function () {
  // initialize stuff
    vjr.comments.setUpUI();
}

$(document).ready(vjr.comments.init);

Javascript에 대한 지식이 제한되어 있기 때문에 이것을 관리하는 더 좋은 방법이 있어야한다는 것을 알고 있지만 지금까지는 잘 작동하고 있습니다.


6

Jquery 중심의 네임 스페이스 방식으로 코드를 구성하면 다음과 같이 보일 수 있습니다 ... Prototype, Ext와 같은 다른 Javascript API와 충돌하지 않습니다.

<script src="jquery/1.3.2/jquery.js" type="text/javascript"></script>
<script type="text/javascript">

var AcmeJQ = jQuery.noConflict(true);
var Acme = {fn: function(){}};

(function($){

    Acme.sayHi = function()
    {
        console.log('Hello');
    };

    Acme.sayBye = function()
    {
        console.log('Good Bye');
    };
})(AcmeJQ);

// Usage
//          Acme.sayHi();
// or
// <a href="#" onclick="Acme.sayHi();">Say Hello</a>


</script>

도움이 되었기를 바랍니다.


이것은 작은화물 운반선으로 나를 때립니다. jQuery.fn는 실제로 jQuery 생성자 함수의 새 인스턴스를 반환 jQuery.prototype하기 때문에에 대한 포인터 $()입니다. jQuery에 '플러그인'을 추가한다는 것은 단순히 프로토 타입을 확장하는 것을 의미합니다. 그러나 당신이하는 일은 그렇지 않으며, 같은 일을 달성하는 더 깨끗한 방법이 있습니다.
Adam Lassek

나는 그가 단순히 정적 함수를 만들고 있다고 생각합니다. 정적 함수를 선언하는 이러한 방법이 허용된다는 것을 jQuery의 문서에서 본 것을 기억합니다.
Alex Heyd

6

OO + MVC의 좋은 원칙은 복잡한 자바 스크립트 앱을 관리하는 데 큰 도움이 될 것입니다.

기본적으로 내 앱과 자바 스크립트를 다음과 같은 친숙한 디자인 (데스크톱 프로그래밍 시대에서 Web 2.0으로 거슬러 올라가는 디자인)으로 구성하고 있습니다.

JS OO와 MVC

이미지의 숫자 값에 대한 설명 :

  1. 내 응용 프로그램의 뷰를 나타내는 위젯. 이것은 확장 가능하고 깔끔하게 분리되어 MVC가 위젯을 스파게티 코드로 변환하지 않고 달성하려고합니다 (HTML에 직접 큰 Javascript 블록을 넣는 웹 응용 프로그램과 동일). 각 위젯은 다른 위젯에서 생성 된 이벤트를 수신하여 다른 위젯을 통해 통신하므로 관리 할 수없는 코드로 이어질 수있는 위젯 간의 강력한 연결이 줄어 듭니다 (스크립트 태그에서 전역 기능을 가리키는 모든 위치에서 onclick을 추가하는 날을 기억하십니까? Urgh ...)
  2. 위젯에서 채우고 서버로 앞뒤로 전달하려는 데이터를 나타내는 오브젝트 모델. 데이터를 모델로 캡슐화하면 응용 프로그램이 데이터 형식에 구애받지 않게됩니다. 예를 들어 자연스럽게 Javascript에서 이러한 객체 모델은 대부분 직렬화되고 JSON으로 직렬화 해제되지만 서버가 통신에 XML을 사용하는 경우 직렬화 / 직렬화 해제 계층을 변경하는 것만으로 모든 위젯 클래스를 변경할 필요는 없습니다. .
  3. 비즈니스 로직 및 서버와의 통신 + 캐싱 계층을 관리하는 컨트롤러 클래스. 이 계층은 서버에 대한 통신 프로토콜을 제어하고 필요한 데이터를 객체 모델에 넣습니다.
  4. 클래스는 해당 네임 스페이스에 깔끔하게 래핑됩니다. Javascript에서 불쾌한 글로벌 네임 스페이스가 어떻게 될 수 있는지 잘 알고 있습니다.

과거에는 파일을 자체 js로 분리하고 일반적인 방법을 사용하여 Javascript에서 OO 원칙을 작성했습니다. JS OO를 작성하는 여러 가지 방법이 있다는 것을 곧 알게 된 문제이며 모든 팀 구성원이 동일한 접근 방식을 가질 필요는 없습니다. 팀이 커지면 (제 경우에는 15 명 이상), Object Oriented Javascript에 대한 표준 접근 방식이 없으므로 복잡해집니다. 동시에 나는 내 자신의 프레임 워크를 작성하고 내가 해결 한 것보다 똑똑한 사람들이 확신하는 일부 작업을 반복하고 싶지 않습니다.

jQuery는 Javascript Framework만큼 엄청나게 좋으며 좋아하지만 프로젝트가 커질수록 특히 OO 연습 표준화를 촉진하기 위해 웹 응용 프로그램을위한 추가 구조가 필요합니다. 나 자신을 위해 여러 실험을 한 후에 YUI3 Base 및 Widget ( http://yuilibrary.com/yui/docs/widget/http://yuilibrary.com/yui/docs/base/index.html ) 인프라가 정확히 내가 필요한 것. 내가 사용하는 몇 가지 이유.

  1. 네임 스페이스 지원을 제공합니다. OO와 깔끔한 코드 구성에 대한 진정한 필요성
  2. 클래스와 객체의 개념을 지원합니다
  3. 클래스에 인스턴스 변수를 추가하는 표준화 수단을 제공합니다.
  4. 클래스 확장을 예쁘게 지원
  5. 생성자와 소멸자를 제공합니다.
  6. 렌더링 및 이벤트 바인딩을 제공합니다
  7. 기본 위젯 프레임 워크가 있습니다
  8. 각 위젯은 이제 표준 이벤트 기반 모델을 사용하여 서로 통신 할 수 있습니다.
  9. 가장 중요한 것은 모든 엔지니어에게 Javascript 개발을위한 OO 표준을 제공한다는 점입니다.

많은보기와는 달리 필자는 jQuery와 YUI3 중에서 선택할 필요가 없습니다. 이 두 사람은 평화롭게 공존 할 수 있습니다. YUI3은 복잡한 웹 앱에 필요한 OO 템플릿을 제공하지만 jQuery는 여전히 우리 팀이 우리 모두에게 친숙하고 친숙한 JS 추상화를 사용하기 쉽게 제공합니다.

YUI3를 사용하여 기본을 모델로 확장하는 클래스와 위젯을 뷰로 확장하는 클래스를 분리하여 MVC 패턴을 만들었습니다. 물론 필요한 논리 및 서버 측 호출을 수행하는 컨트롤러 클래스가 있습니다.

위젯은 이벤트 기반 모델을 사용하고 이벤트를 듣고 사전 정의 된 인터페이스를 기반으로 필요한 태스크를 수행하여 서로 통신 할 수 있습니다. 간단히 말해서, OO + MVC 구조를 JS에 넣는 것은 기쁨입니다.

면책 조항입니다. Yahoo!에서 일하지 않습니다! 원래 질문에서 제기 한 것과 동일한 문제에 대처하려는 건축가입니다. 누군가가 동등한 OO 프레임 워크를 찾으면 이것이 잘 작동한다고 생각합니다. 원칙적으로이 질문은 다른 기술에도 적용됩니다. 우리의 프로그래밍 일을 더 잘 관리 할 수 ​​있도록 OO Principles + MVC를 만든 모든 사람들에게 감사합니다.


5

내가 사용하는 Dojo의 패키지 관리 ( dojo.requiredojo.provide) 및 (클래스 시스템을 dojo.declare별도의 파일로 내 수업 / 위젯을 모두 모듈화하는 것이 간단한 다중 상속을 허용). 이를 통해 코드를 체계적으로 관리 할 수있을뿐만 아니라 클래스 / 위젯을로드 / 제대로로드 할 수 있습니다.


3

며칠 전에 37Signals의 사람들 은 RTE 컨트롤을 발표했습니다 . 그들은 일종의 전 처리기 명령을 사용하여 자바 스크립트 파일을 묶는 라이브러리를 만들었습니다.

JS 파일을 분리 한 다음 결국 하나로 병합하기 위해 사용하고 있습니다. 그렇게하면 걱정을 분리하고 결국 파이프를 통과하는 파일이 하나만 있습니다 (지워지지 않습니다).

템플릿에서 개발 모드에 있는지 확인하고 별도의 파일을 포함하고 프로덕션에있는 경우 최종 파일 (자체를 "빌드"해야 함)을 포함하십시오.


1
getsprockets.org 는 직접 링크입니다
Matt Gardner

3

가짜 클래스를 만들고 의미가있는 별도의 함수에 던져 질 수있는 것은 무엇이든해야합니다. 또한 스파게티 코드를 작성하지 말고 많은 부분을 주석 처리하십시오. 예를 들어, 나의 이상을 묘사하는 넌센스 코드. 분명히 실제 생활에서는 기본적으로 기능을 포함하는 많은 라이브러리를 작성합니다.

$(function(){
    //Preload header images
    $('a.rollover').preload();

    //Create new datagrid
    var dGrid = datagrid.init({width: 5, url: 'datalist.txt', style: 'aero'});
});

var datagrid = {
    init: function(w, url, style){
        //Rendering code goes here for style / width
        //code etc

        //Fetch data in
        $.get(url, {}, function(data){
            data = data.split('\n');
            for(var i=0; i < data.length; i++){
                //fetching data
            }
        })
    },
    refresh: function(deep){
        //more functions etc.
    }
};


2

아마도 이것이 DDD (Domain-Driven Design)와 관련이 있다고 생각합니다. 공식 API가 없지만 작업중 인 응용 프로그램은 서버 측 코드 (클래스 / 파일 이름 등)를 통해 힌트를 제공합니다. 이를 통해 전체 문제 도메인의 컨테이너로 최상위 개체를 만들었습니다. 그런 다음 필요한 곳에 네임 스페이스를 추가했습니다.

var App;
(function()
{
    App = new Domain( 'test' );

    function Domain( id )
    {
        this.id = id;
        this.echo = function echo( s )
        {
            alert( s );
        }
        return this;
    }
})();

// separate file
(function(Domain)
{
    Domain.Console = new Console();

    function Console()
    {
        this.Log = function Log( s )
        {
            console.log( s );
        }
        return this;
    }
})(App);

// implementation
App.Console.Log('foo');

2

JavaScript 조직은 다음을 사용하고 있습니다

  1. 모든 자바 스크립트 폴더
  2. 페이지 레벨 자바 스크립트는 동일한 페이지 이름을 가진 자체 파일을 가져옵니다. ProductDetail.aspx는 ProductDetail.js입니다.
  3. 라이브러리 파일의 javascript 폴더 안에 lib 폴더가 있습니다.
  4. 응용 프로그램 전체에서 사용하려는 lib 폴더에 관련 라이브러리 함수를 넣습니다.
  5. Ajax는 javascript 폴더 외부로 이동하여 자체 폴더를 얻는 유일한 Javascript입니다. 그런 다음 클라이언트와 서버 두 개의 하위 폴더를 추가합니다.
  6. 클라이언트 폴더는 모든 .js 파일을 가져 오는 반면 서버 폴더는 모든 서버 측 파일을 가져옵니다.

파일 구성에 좋습니다. 코드로 그렇게합니다. 그러나 결국에는 코드를 컴파일합니다 .dll이라고합시다. 자바 스크립트로도 필요하거나 페이지 당 15 개의 js 파일을 요청하게됩니다.
graffic

페이지 당 15 개의 JS 파일을 요청하는 데 아무런 문제가 없습니다. 브라우저는 어쨌든 후속 요청을 위해이를 캐시합니다.
Marnen Laibow-Koser 3

@ MarnenLaibow-Koser 페이지에서 15 개의 JS 파일을 요청하는 유일한 문제는 브라우저가 한 번에 처리 할 수있는 HTTP 요청 수입니다. 따라서 하나의 파일로 묶으면 브라우저가 다른 필요한 파일을 동시에 요청할 수 있습니다.
iwasrobbed에

사실이지만 첫 두 번의 방문 후에는 브라우저의 캐시에 있으므로 HTTP 연결이 필요하지 않습니다.
Marnen Laibow-Koser

2

나는이 작은 것을 사용하고 있습니다. JS 및 HTML 템플릿 모두에 대한 'include'지시문을 제공합니다. 혼란을 완전히 없애줍니다.

https://github.com/gaperton/include.js/

$.include({
    html: "my_template.html" // include template from file...
})
.define( function( _ ){ // define module...
    _.exports = function widget( $this, a_data, a_events ){ // exporting function...
        _.html.renderTo( $this, a_data ); // which expands template inside of $this.

        $this.find( "#ok").click( a_events.on_click ); // throw event up to the caller...
        $this.find( "#refresh").click( function(){
            widget( $this, a_data, a_events ); // ...and update ourself. Yep, in that easy way.
        });
    }
});

2

당신은 사용할 수 있습니다 JQuery와 MX 는 모델, 뷰, 컨트롤러를 사용할 수 있도록 스크립트의 집합입니다 (javascriptMVC에서 사용 참조). 나는 프로젝트에서 그것을 사용했고 압축으로 인해 최소한의 스크립트 크기로 구조적 자바 스크립트를 만드는 데 도움을주었습니다. 이것은 컨트롤러 예입니다.

$.Controller.extend('Todos',{
  ".todo mouseover" : function( el, ev ) {
   el.css("backgroundColor","red")
  },
  ".todo mouseout" : function( el, ev ) {
   el.css("backgroundColor","")
  },
  ".create click" : function() {
   this.find("ol").append("<li class='todo'>New Todo</li>"); 
  }
})

new Todos($('#todos'));

뷰 및 모델 파트에 관심이없는 경우 jquerymx 의 컨트롤러 측만 사용할 수도 있습니다 .


1

당신의 질문은 작년 말 저를 괴롭힌 것입니다. 차이점은 개인 및 공개 방법에 대해 들어 본 적이없는 새로운 개발자에게 코드를 전달하는 것입니다. 나는 간단한 것을 만들어야했습니다.

최종 결과는 객체 리터럴을 jQuery로 변환하는 작은 (약 1KB) 프레임 워크였습니다. 구문은 시각적으로 스캔하기가 더 쉽고 js가 실제로 커지면 재사용 가능한 쿼리를 작성하여 사용 된 선택기,로드 된 파일, 종속 함수 등을 찾을 수 있습니다.

여기에 작은 프레임 워크를 게시하는 것은 실용적이지 않으므로 예제가 있는 블로그 게시물을 작성했습니다 (첫 번째는 모험이었습니다!). 당신은 살펴볼 수 있습니다.

몇 분 동안 체크 아웃 해야하는 다른 사람들에게 의견을 보내 주셔서 감사합니다.

FireFox는 객체 질의 예제를 위해 toSource ()를 지원하므로 권장됩니다.

건배!

아담


0

벤 놀란의 행동에서 영감을 얻은 커스텀 스크립트를 사용합니다 (더 이상 슬프게도 현재 링크를 찾을 수 없습니다). 이러한 이벤트 핸들러는 예를 들어 className 또는 Id 요소에 의해 트리거됩니다. 예:

Behaviour.register({ 
    'a.delete-post': function(element) {
        element.observe('click', function(event) { ... });
    },

    'a.anotherlink': function(element) {
        element.observe('click', function(event) { ... });
    }

});

전역 동작을 포함하는 라이브러리를 제외한 대부분의 Javascript 라이브러리를 즉시 포함하고 싶습니다. 내가 사용하는 젠드 프레임 워크의 headScript () 자리 도우미 이를 위해,하지만 당신은 할 수 즉시 다른 스크립트를로드하는 자바 스크립트 사용Ajile 예를 들어.


이것이 당신이 찾고 있었던 것입니까? koders.com/javascript/…
DOK

그래, 그게 다야! :) 링크 뒤의 코드는 내가 영감을 얻은 버전보다 훨씬 최신 것 같습니다. 노력해 주셔서 감사합니다!
Aron Rotteveel

0

서버 측 언어가 무엇인지 언급하지 않았습니다. 또는 서버 측에서 사용중인 프레임 워크 (있는 경우)가 더 적절합니다.

IME, 나는 서버 측에서 일을 조직하고 모든 것이 웹 페이지로 흔들 리게합니다. 이 프레임 워크에는 모든 페이지가로드해야하는 JS뿐만 아니라 생성 된 마크 업과 함께 작동하는 JS 프래그먼트를 구성하는 작업이 제공됩니다. 이러한 조각은 일반적으로 두 번 이상 방출하고 싶지 않으므로 해당 코드의 프레임 워크로 추상화되어 문제를 해결합니다. :-)

자체 JS를 생성해야하는 최종 페이지의 경우 일반적으로 생성 된 마크 업에 논리적 구조가 있음을 알게됩니다. 이러한 현지화 된 JS는 종종 그러한 구조의 시작 및 / 또는 끝에서 조립 될 수 있습니다.

이 중 어느 것도 효율적인 JavaScript를 작성하는 데 도움이되지 않습니다! :-)


당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.