>웹 프론트엔드 >JS 튜토리얼 >JavaScript 모듈화에 대한 간략한 분석

JavaScript 모듈화에 대한 간략한 분석

高洛峰
高洛峰원래의
2017-02-04 16:24:581139검색

서문

모듈화와 관련하여 가장 직접적인 표현은 우리가 작성하는 require 및 import 키워드입니다. 관련 정보를 확인하면 CommonJS, CMD AMD, RequireJS, SeaJS라는 용어를 반드시 접하게 될 것입니다. , 등 이상한 프레임. 예를 들어 SeaJS 공식 웹사이트에서는 다음과 같이 설명합니다. "간단하고 친숙한 모듈 정의 사양, Sea.js는 CMD 사양을 따릅니다. 자연스럽고 직관적인 코드 구성, 종속성 자동 로딩..."

As 프론트 엔드 초보자인데 솔직히 그는 혼란스러워 보였고 이해하지 못했습니다. 나의 평소 스타일에 따르면, 무언가를 소개하기 전에 항상 그것이 왜 필요한지 설명해야 합니다.

JavaScript 기본

클라이언트에서 작업하는 학생은 OC의 #import "classname", Swift의 모듈 및 파일 수정자, Java의 import package+class 모드에 익숙해야 합니다. 우리는 파일을 참조하는 것이 클래스를 참조하는 패턴에 익숙합니다. 그러나 JavaScript와 같은 동적 언어에서는 상황이 변경되었습니다. 예:







Hello Wrold



// index.js
function onPress() {
var p = document.getElementById('hello');
p.innerHTML = 'Hello bestswifter';
}

< HTML의 script> 태그는 가져오기로 이해될 수 있으므로 버튼의 onclick 이벤트가 index.js에 정의된 onPress 함수를 호출할 수 있습니다.

프로젝트가 진행되면서 클릭한 텍스트가 동적으로 생성되고 다른 JS 파일에 의해 생성되어야 한다는 것을 알게 되면 간단한 index.js로는 해당 작업을 수행할 수 없게 됩니다. 생성된 콘텐츠가 math.js 파일에 정의되어 있다고 가정합니다.

// math.js
function add(a, b) {
return a + b;
}

클라이언트의 생각에 따르면 이때 index.js 파일은 다음과 같이 작성해야 합니다.

// index.js
import "math.js"

함수 onPress() {
var p = document.getElementById('hello');
p.innerHTML = add(1, 2);
}

안타깝게도 JavaScript는 지원하지 않습니다. 가져오기 방식을 지원하지 않습니다. 이는 다른 JS 파일의 메소드를 하나의 JS 파일에서 참조할 수 없음을 의미합니다. 올바른 해결책은 index.js에서 직접 add 메소드를 호출하고 index.html에서 math.js를 참조하는 것입니다:





< /head>


Hello World





// index.js
function onPress() {
var p = document. getElementById('hello');
p.innerHTML = add(1, 2);
}

이런 작성 방식이 우아하지 않다는 것을 알 수 있습니다. add 메소드를 호출할 수 있는지 여부는 전적으로 HTML 파일이 다른 JS 파일을 올바르게 참조했는지 여부에 따라 달라집니다.

사전 모듈화

방금 언급한 문제점은 실제로 두 가지 유형으로 나눌 수 있습니다.

index.js는 가져올 수 없으며 HTML 참조에 의존합니다.

index.js에서는 add 메소드의 소스를 구별할 수 없고 네임스페이스의 개념이 빠져있습니다

첫 번째 질문은 나중에 두 번째 질문부터 답변해 드리겠습니다. object를 먼저 노출하면 사용자가 이 개체의 여러 메서드를 호출할 수 있습니다.

//index.js
function onPress() {
var p = document.getElementById( ' 안녕하세요');
p.innerHTML = math.add(1, 2);
}

//math.js
var math = {
base: 0,
추가: function(a, b) {
return a + b + base;
},
};

이미 사용 가능한 것을 볼 수 있습니다. index.js 네임스페이스(즉, 수학)의 단순화된 버전을 지정합니다. 하지만 여전히 작은 문제가 있습니다. 예를 들어 기본 속성이 외부 세계에 노출되고 수정될 수도 있습니다. 따라서 더 좋은 방법은 내부 속성을 숨기기 위해 클로저에서 수학을 정의하는 것입니다.

// math.js
var math = (function() {
var base = 0;
return {
추가: 함수(a, b) {
return a + b + base;
},
};
})();

지금까지 모듈의 정의와 사용법을 구현했습니다. 그러나 모듈화의 본질 중 하나는 네임스페이스에 있습니다. 이는 수학 모듈이 전역적이지 않고 요청 시 가져오기를 희망한다는 것을 의미합니다. 이러한 방식으로 여러 파일이 동일한 이름을 가진 객체를 노출하더라도 아무 일도 일어나지 않을 것입니다. 문제. node.js와 마찬가지로 노출해야 하는 모듈은 자체 내보내기 콘텐츠를 정의한 다음 호출자가 require 메서드를 사용합니다.

실제로 node.js의 작업 모드를 간단히 시뮬레이션하고 중간 레이어를 추가하여 문제를 해결할 수 있습니다. 먼저 전역 변수를 정의합니다.

// global.js
var module = {
exports: {}, // 노출된 모든 콘텐츠를 저장하는 데 사용됩니다
};

  그런 다음 math.js에 객체를 노출합니다.

var math = ( function() {
var base = 0;
return {
add: function(a, b) {
return a + b + base;
},
} ;
})();

module.exports.math = math;

이제 사용자 index.js는 다음과 같아야 합니다.

var math = module .exports.math;

function onPress() {
var p = document.getElementById('hello');
// math
p.innerHTML = math.add(1, 2 );
}

기존 모듈형 솔루션

위의 간단한 모듈화 방식에는 몇 가지 사소한 문제가 있습니다. 우선, index.js는 math.js 실행에 엄격하게 의존해야 합니다. 왜냐하면 math.js가 실행된 후에만 전역 module.export에 등록되기 때문입니다. 이를 위해서는 개발자가 js 파일의 로드 순서를 수동으로 관리해야 합니다. 프로젝트가 커질수록 종속성을 유지하는 것이 점점 더 복잡해집니다.

둘째, JS 파일을 로드할 때 브라우저가 웹 페이지 렌더링을 중지하므로 JS 파일의 비동기 온디맨드 로드도 필요합니다.

마지막 문제는 이전에 제공된 단순화된 모듈화 솔루션이 모듈 네임스페이스를 해결하지 못한다는 것입니다. 동일한 내보내기가 여전히 이전 콘텐츠를 대체하며, 해결 방법은 "파일 경로< ;–> 콘텐츠 내보내기"를 유지하는 것입니다. " 테이블을 선택하고 파일 경로를 기준으로 로드합니다.

위의 요구 사항을 바탕으로 다양한 모듈식 솔루션 세트가 시장에 출시되었습니다. 여러 가지 표준이 존재하는 이유는 사실 프론트엔드의 특성 때문입니다. 통일된 표준이 없기 때문에 많은 경우 위에서 언급한 내보내기 및 요구와 같은 작업을 수행할 때 모든 사람이 규칙에 의존합니다. 코드 제공자가 내보내기 내용을 module.exports에 저장하고 사용자가 module.export를 읽는다면 당연히 헛된 일입니다. 뿐만 아니라 각 사양의 구현 방법과 사용 시나리오도 다릅니다.

CommonJS

더 잘 알려진 사양으로는 CommonJS, AMD 및 CMD가 있습니다. 잘 알려진 프레임워크인 Node.js, RequireJS 및 Seajs는 각각 위 사양을 구현합니다.

가장 초기 사양은 Node.js에서 사용하는 CommonJS입니다. 이 사양은 JS 스크립트를 동기식으로 로드하는 이전 접근 방식과 유사합니다. 파일이 디스크에 저장되기 때문에 서버 측에서 이 작업을 수행하는 데에는 문제가 없습니다. 그러나 브라우저의 특성에 따라 JS 스크립트를 비동기식으로 로드해야 합니다. 그렇지 않으면 응답이 손실되므로 CommonJS 사양을 사용할 수 없습니다. 브라우저에서 직접 사용할 수 있습니다.

AMD 

브라우저 측의 유명한 모듈 관리 도구인 Require.js가 비동기적으로 로드되어 Webworker의 importScripts(url) 함수를 통해 JS 스크립트를 로드한 후 원래 등록된 콜백을 실행합니다. . Require.js의 작성 방법은 다음과 같습니다.

require(['myModule1', 'myModule2'], function (m1, m2){
// 기본 콜백 로직
m1.printName() ;
m2.printName();
});

이 두 모듈은 비동기적으로 다운로드되기 때문에 어떤 모듈을 먼저 다운로드하여 실행할지는 확실하지 않지만 확실하다. 콜백은 모든 종속 항목이 로드된 후에 실행되어야 합니다.

이러한 Require.js 작성 방법을 프론트 로딩이라고도 합니다. 모든 종속성은 기본 로직을 작성하기 전에 지정되어야 하며 이러한 종속성은 즉시 비동기식으로 로드됩니다.

 Require.js에서 파생된 사양을 AMD(Asynchronous Module Definition)라고 합니다.

CMD

또 다른 뛰어난 모듈 관리 도구는 Sea.js입니다. 작성 방법은 다음과 같습니다.

define(function(require,exports, module) {
var foo = require('foo'); // 동기화
foo.add(1, 2);
...
require.async('math', function(math) { // 비동기
math.add(1, 2);
});
});

Sea.js를 Nearest Loading이라고도 하는데, 쓰는 방식으로 보면 알 수 있습니다. Require.js와의 차이점을 확인하세요. 종속성을 사용해야 하는 경우에만 종속성을 선언할 수 있습니다.

Sea.js는 종속성을 발견하면 JS 파일만 다운로드하고 실행하지 않습니다. 대신 기본 로직을 처음부터 실행하기 전에 모든 종속 JS 스크립트가 다운로드될 때까지 기다립니다. 따라서 종속 모듈의 실행 순서는 쓰기 순서와 정확히 동일합니다.

Sea.js에서 파생된 사양을 CMD(Common Module Definition)라고 합니다.

 ES 6 모듈화

 ES6에서는 모듈을 내보내려면 내보내기 키워드를 사용하고 모듈을 참조하려면 가져오기 키워드를 사용합니다. ES 6의 이 표준 세트는 현재 표준과 직접적인 관련이 없으며 현재 이를 직접 지원할 수 있는 JS 엔진은 거의 없습니다. 따라서 Babel이 실제로 수행하는 작업은 지원되지 않는 가져오기를 현재 지원되는 요구 사항으로 변환하는 것입니다.

현재 import와 require 사용 사이에는 거의 차이가 없지만(본질적으로 동일한 것임) import 키워드를 사용하는 것이 좋습니다. JS 엔진이 ES 6 import 키워드를 구문 분석할 수 있으면 전체 구현이 다음과 같기 때문입니다. 마찬가지로 현재 큰 변화가 일어나고 있습니다. 지금 import 키워드를 사용하기 시작하면 향후 코드 변경 사항은 매우 작습니다.

경유: http://fullstack.blog/2017/01/25/JavaScript%20%E6%A8%A1%E5%9D%97%E5%8C%96%E7%AE%80% E8%BF%B0/

자바스크립트 모듈화 분석과 관련된 더 많은 글은 PHP 중국어 홈페이지를 주목해주세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.