JS 의 모듈 화 는 어떻게 실현 되 었 는 지 상세 하 게 설명 합 니 다.

7614 단어 JavaScript모듈 화
JS 가 처음에 포 지 셔 닝 한 원인(처음에 너무 복잡 한 장면 에 응 용 될 줄 몰 랐 기 때문에 그 자체 가 모듈 시스템 을 제공 하지 않 았 고 응용 이 복잡 해 지면 서 모듈 화 는 반드시 해결 해 야 할 문제 가 되 었 다.피 맥 의 깊이 있 는 원리 원칙 에 따라 모듈 화 된 베일 을 벗 길 필요 가 있다.
1.모듈 화 해결 해 야 할 문제
한 가지 물건 에 대해 깊이 있 게 분석 하려 면 목적 을 가지 고 볼 필요 가 있다.모듈 화 에서 해결 해 야 할 문 제 는 한 마디 로 요약 할 수 있다.
전역 오염 없 이 더 좋 은 조직 프로젝트 코드
간단 한 밤 을 들 어 보 세 요.우 리 는 지금 다음 과 같은 코드 가 있 습 니 다.

function doSomething () {
 const a = 10;
 const b = 11;
 const add = function (a + b) {
  return a + b
 }
 add (a + b)
}
현실 적 인 응용 장면 에서 doSomething 은 많은 일 을 해 야 할 수도 있 습 니 다.add 함수 도 더욱 복잡 하고 재 활용 할 수 있 습 니 다.그러면 우 리 는 add 함 수 를 하나의 단독 파일 에 독립 시 킬 수 있 기 를 바 랍 니 다.그래서:

// doSomething.js   
const add = require('add.js');
const a = 10;
const b = 11;
add(a+ b);

// add.js   
function add (a, b) {
 return a + b;
}
module.exports = add;
이렇게 하 는 목적 은 분명 하 다.더 좋 은 조직 프로젝트 코드 는 두 파일 중의 require 와 module.exports 를 알 수 있다.현재 의 하나님 의 시각 에서 볼 때 이것 은 CommonJS 규범(뒷글 에 규범 을 전문 적 으로 설명 하 는 장 이 있 을 것 이다)중의 키 워드 를 나타 내 는데 각각 도입 과 도 출 을 대표 하고 규범 을 떠 나 서 말하자면이것 은 사실 우리 가 모듈 화 하 는 길에 해결 해 야 할 문제 이다.또한,add 모듈 은 재 활용 이 필요 하지만,add 를 도입 할 때 전체 오염 을 일 으 키 기 를 원 하지 않 습 니 다.
2.도입 한 모듈 은 어떻게 운행 합 니까?
상기 예 에서 우 리 는 코드 를 두 모듈 파일 로 나 누 었 습 니 다.전체적인 오염 을 일 으 키 지 않 는 상황 에서 require 를 어떻게 실현 해 야 예 중의 코드 를 정상 적 으로 운행 할 수 있 습 니까?
모듈 파일 코드 의 불 러 오 는 과정 을 고려 하지 않 고 require 가 모듈 파일 에서 코드 문자열 을 읽 을 수 있다 고 가정 하면 require 는 이렇게 실현 할 수 있 습 니 다.

function require (path) {
  // lode      path              
  // let code = load(path);
  //     load    ,       add      
  let code = 'function add(a, b) {return a+b}; module.exports = add';
  //      
  code = `(function(module) {$[code]})(context)`
  //     exports,      
  let context = {};
  //     ,        context
  const run = new Function('context', code);
  run(context, code);
  //       
  return context.exports;
}
이것 은 몇 가지 요점 이 있다.
1)전역 오염 을 일 으 키 지 않 기 위해 서 는 코드 문자열 을 패 킷 형식 으로 밀봉 하고 키워드 module.exports 를 내 보 내야 합 니 다.module 은 외부 와 연 결 된 유일한 캐리어 입 니 다.패 킷 익명 함수 의 입 참 으로 인용 측 에서 들 어 오 는 문맥 context 와 연결 해 야 합 니 다.
2)new Function 을 사용 하여 코드 문자열 을 실행 합 니 다.대부분의 학생 들 은 new Function 에 익숙 하지 않 을 것 입 니 다.일반적인 상황 에서 함 수 를 정의 할 때 이 럴 필요 가 없 기 때 문 입 니 다.Function 류 로 함 수 를 직접 만 들 수 있다 는 것 을 알 아야 합 니 다.문법 은 다음 과 같 습 니 다.

var function_name = new function(arg1, arg2, ..., argN, function_body)
위의 형식 에서 모든 arg 는 하나의 매개 변수 이 고 마지막 매개 변 수 는 함수 주체(실행 할 코드)입 니 다.이 매개 변 수 는 문자열 이 어야 합 니 다.즉,이 를 사용 하여 문자열 코드 를 실행 할 수 있 습 니 다.eval 과 유사 하 며,eval 에 비해 문자열 코드 의 일부 변수의 값 을 매개 변수 로 전송 할 수 있 습 니 다.
3)왜 규범 적 으로 키 워드 를 내 보 내 는 지 궁금 한 적 이 있 으 면 exports 만 있 고 우리 가 실제 사용 하 는 과정 에서 module.exports(Node 코드 를 쓴 사람 은 낯 설 지 않 을 것 입 니 다)를 사용 해 야 합 니 다.이 코드 에서 답 을 찾 을 수 있 습 니 다.exports 로 만 context 를 받 으 면그러면 exports 의 재 할당 값 은 context 에 아무런 영향 을 주지 않 습 니 다.(매개 변수의 주소 전달)코드 를 다음 과 같은 형식 으로 바 꾸 고 다시 뛰 는 것 을 믿 지 않 습 니 다.

결 과 를 시연 하 다.
3.코드 불 러 오 는 방식
코드 의 실행 문 제 를 해결 하고 모듈 파일 코드 의 불 러 오 는 문 제 를 해결 해 야 합 니 다.상기 사례 에 따 르 면 모듈 파일 코드 를 문자열 로 불 러 오 는 것 이 목표 입 니 다.
Node 용기 에 서 는 모든 모듈 파일 이 로 컬 에 있 습 니 다.로 컬 디스크 에서 모듈 파일 을 읽 고 문자열 코드 를 불 러 오고 상기 절 차 를 가면 됩 니 다.사실은 Node 비 내장,핵심,c+모듈 의 불 러 오기 실행 방식 이 대체적으로 이와 같다 는 것 을 증명 한다.(new Function 을 사용 하 는 것 은 아니 지만 비슷 한 방법 이기 도 하 다)
RN/Weex 용기 에 원 격 bundle.js 를 불 러 오 려 면 Native 의 능력 을 통 해 원 격 js 파일 을 요청 하고 문자열 코드 로 불 러 오 면 됩 니 다.
브 라 우 저 환경 에서 모든 Js 모듈 은 원 격 으로 읽 어야 합 니 다.어색 한 것 은 브 라 우 저가 제공 하 는 능력 에 제한 을 받 아 ajax 를 통 해 원 격 js 파일 을 문자열 코드 로 직접 읽 을 수 없습니다.전제조건 을 달성 할 수 없 으 면,상술 한 운행 전략 은 통 하지 않 고,다른 길 을 개척 할 수 밖 에 없다.
이것 이 바로 CommonJs 규범 이 생 긴 이유 이 고,왜 AMD/CMD 규범 이 생 긴 이유 이다.
그럼 브 라 우 저 에 서 는 어떻게 하 는 거 예요?브 라 우 저 에서 Js 를 통 해 원 격 Js 모듈 파일 을 동적 으로 불 러 오 려 면노드 를 동적 으로 삽입 해 야 합 니 다.

// 摘抄自 require.js 的一段代码
var node = config.xhtml ?
        document.createElementNS('http://www.w3.org/1999/xhtml', 'html:script') :
        document.createElement('script');
node.type = config.scriptType || 'text/javascript';
node.charset = 'utf-8';
node.async = true;
node.setAttribute('data-requirecontext', context.contextName);
node.setAttribute('data-requiremodule', moduleName);
node.addEventListener('load', context.onScriptLoad, false);
node.addEventListener('error', context.onScriptError, false);
탭 의 src 를 설정 한 후 코드 가 다운로드 가 완료 되면 바로 실 행 됩 니 다.더 이상 패키지 로 봉인 할 수 없 기 때문에 파일 모듈 은 정의 초기 에 글 을 써 야 합 니 다.이것 이 바로 우리 가 잘 알 고 있 는 AMD/CMD 규범 중의 define 입 니 다.시작 하 는 add.js 는 다시 고 쳐 써 야 합 니 다.

// add.js 文件
define ('add',function () {
  function add (a, b) {
   return a + b;
  }
  return add;
})
그리고 define 의 실현 에 있어 서 가장 중요 한 것 은 callback 의 실행 결 과 를 context 의 한 모듈 배열 에 등록 하 는 것 입 니 다.

  context.modules = {}
  function define(name, callback) {
    context.modules[name] = callback && callback()
  }
그래서 require 는 context.modules 에서 모듈 이름 에 따라 모듈 을 불 러 올 수 있 습 니 다.스스로'requirejs'를 쓰 는 충동 감 이 있 는 것 아 닙 니까?
구체 적 인 AMD 실현 은 물론 복잡 할 것 입 니 다.제어 모듈 불 러 오기 순서,모듈 의존 등 이 필요 합 니 다.그러나 그 중의 영혼 을 알 게 되 었 으 니 require.js 의 소스 코드 를 정독 하 는 것 도 어 려 운 일이 아 닙 니 다.
4.웹 팩 의 모듈 화
웹 팩 도 비동기 모듈 을 설정 할 수 있 습 니 다.비동기 모듈 로 설정 되 었 을 때 브 라 우 저 환경 에서 도 동적 삽입방식 으로 원 격 모듈 을 불 러 옵 니 다.대부분의 경우 모듈 의 불 러 오 는 방식 은 Node 의 로 컬 디스크 와 동기 화 되 는 방식 입 니 다.
웹 팩 은 모듈 화 능력 을 제외 하고 개발 워 크 플 로 를 보조 적 으로 보완 하 는 도구 임 을 잊 어 버 렸 다.즉,웹 팩 의 모듈 화 는 개발 단계 에서 이 루어 졌 고 웹 팩 으로 구 축 된 작업 환경 이다.개발 단계 에 서 는 독립 된 모듈 파일 이지 만 실행 할 때 합 쳐 진 파일 이다.
따라서 웹 팩 은 실행 되 지 않 을 때 모듈 화 방안(CommonJs 기반)입 니 다.비동기 모듈 을 설정 할 때 만 비동기 모듈 에 대한 로드 가 실 행 될 때(AMD 기반)입 니 다.
5.모듈 화 규범
통용 되 는 문 제 는 해결 하 는 과정 에서 항상 규범 이 형성 되 는데,위의 글 은 이미 여러 차례 CommonJs,AMD,CMD 를 언급 하 였 으 니,편폭 을 들 여 규범 을 말 할 필요 가 있다.
Js 의 모듈 화 규범 은 Js 를 백 엔 드 로 확장 하 겠 다 는 생각 에서 비롯 되 었 다.Js 가 Python,Ruby,자바 처럼 대형 응용 을 개발 하 는 기초 능력 을 갖 추 려 면 모듈 화 규범 이 없어 서 는 안 된다.CommonJS 규범 의 제 기 는 Js 를 위해 아름 다운 비 전 을 제 정 했 습 니 다.Js 가 어느 곳 에서 든 운행 할 수 있 기 를 바 랍 니 다.이 는 다음 과 같 지만 이에 국한 되 지 않 습 니 다.
서버 쪽 Js 응용
명령 행 도구
데스크 톱 응용 프로그램
혼합 응용
CommonJS 가 모듈 에 대한 정 의 는 복잡 하지 않 고 주로 모듈 참조,모듈 정의 와 모듈 표지 로 나 뉜 다.
모듈 참조:require 방법 으로 모듈 을 도입 합 니 다모듈 정의:exports 내 보 내기 모듈 대상 을 사용 합 니 다모듈 표지:require 방법 에 들 어 오 는 매개 변수,작은 낙타 봉 이름 의 문자열,상대 경로 또는 절대 경로
모듈 표시
CommonJs 규범 은 Node 에서 이 채 를 띠 고 서로 추진 하지만 브 라 우 저 에서 네트워크 의 원인 을 감안 하여 동기 화 방식 으로 모듈 을 불 러 오 는 것 은 실 용적 이지 않 습 니 다.분쟁 을 겪 은 후에 AMD 규범 은 최종 적 으로 전단 장면 에서 이 겼 습 니 다(전 칭 Asynchronous Module Definition,즉'비동기 모듈 정의')
AMD 란 무엇 입 니까?왜 AMD 가 필요 합 니까?앞에서 말 한 모듈 화 실현 의 추론 과정 에서 너 는 답 을 찾 을 수 있 을 것 이다.
그 밖 에 국내 옥 백 이 제기 한 CMD 규범 도 있다.AMD 와 CMD 의 차 이 는 주로 전 자 는 정의 초기 에 모든 의존 도 를 밝 혀 야 하고 후 자 는 임의의 시기 에 모듈 을 동적 으로 도입 할 수 있다 는 것 이다.CMD 는 CommonJS 에 더 가 깝 습 니 다.
두 가지 규범 은 모두 원 격 네트워크 에서 모듈 을 불 러 와 야 한다.다른 점 은 전 자 는 사전 로드 이 고 후 자 는 로드 지연 이다.
총화
만약 마음 이 있다 면 본 고의 추론 을 참조 하여'your RequireJs'를 실현 할 수 있 습 니 다.반복 적 으로 바퀴 를 만 드 는 것 만큼 지식 을 침전 시 킬 수 있 는 것 은 없습니다~
이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.

좋은 웹페이지 즐겨찾기