>웹 프론트엔드 >JS 튜토리얼 >Javascript 모듈성에 대한 자세한 소개

Javascript 모듈성에 대한 자세한 소개

不言
不言원래의
2018-09-05 11:55:341646검색

이 글은 Javascript 모듈화에 대한 자세한 소개를 담고 있습니다. 도움이 필요한 친구들이 참고할 수 있기를 바랍니다.

머리말

웹 기술의 활발한 발전과 이를 기반으로 하는 인프라가 점점 완벽해지면서 프런트엔드 분야는 점차 브라우저에서 서버(Node.js), 데스크톱(PC, Android, iOS), JavaScript가 이러한 애플리케이션의 핵심 부분을 담당하는 사물 인터넷 장치(IoT)의 규모와 복잡성이 기하급수적으로 증가함에 따라 소프트웨어 엔지니어링 시스템도 확립됩니다(협업 개발, 단위 테스트, 요구 사항 및 결함 관리 등). ), 모듈형 프로그래밍에 대한 수요가 점점 더 시급해지고 있습니다.

JavaScript의 모듈형 프로그래밍 지원은 아직 표준화되지 않았으며 한동안 이 중요한 작업을 수행하기 어려웠습니다. 전 세계의 기사들이 모든 장애물을 극복하고 화전 농업에서 미래 지향적 농업으로 전환했습니다. 모듈식 솔루션;

Concept

모듈식 프로그래밍은 __상대적으로 독립적이고 재사용 가능한 모듈__을 결합하여 기능을 구현하는 것입니다. 두 가지 핵심 부분은 __정의 모듈__입니다. 모듈을 정의할 때 각 모듈 내부의 실행 로직은 외부 세계에서 인식되지 않고 일부 메소드와 데이터만 내보내(노출)

  • 모듈이 도입되면 동기/비동기적으로 로드됩니다.

  • Slash-and-burn farm

  • JavaScript 언어 레벨은 모듈식 솔루션을 제공하지 않지만 __객체 지향__ 언어 기능을 사용하여 __디자인 패턴__을 지원합니다. , 몇 가지 간단한 모듈식 아키텍처가 실현될 수 있습니다. 고전적인 사례는 모듈성을 달성하기 위해 싱글톤 패턴을 사용하는 것입니다. 이는 모듈을 더 잘 캡슐화하고 이를 사용해야 하는 사용자에게 정보의 일부만 노출할 수 있습니다.
// Define a module
var moduleA = (function ($, doc) {
  var methodA = function() {};
  var dataA = {};
  return {
    methodA: methodA,
    dataA: dataA
  };
})(jQuery, document);

// Use a module
var result = moduleA.mehodA();

직관적으로, 즉시 실행 함수(IIFE)를 사용하여 종속성을 선언하고 데이터를 내보내는 것은 현재 모듈식 솔루션과 크게 다르지 않지만 본질적으로 다르며 충족할 수 없는 몇 가지 중요한 문제가 있습니다. 선언된 종속성은 자동으로 도입되도록 강제되지 않습니다. 즉, 모듈을 정의하기 전에 종속 모듈 코드를 수동으로 도입해야 합니다.

모듈이 정의되면 해당 코드는 이미 실행 프로세스를 완료했으며 요청 시 로드할 수 없습니다.

  • 파일 전체에서 모듈을 사용하는 경우 모듈을 전역 변수(창)에 마운트해야 합니다.

  • AMD와 CMD는 두 부분으로 나뉩니다.

    주제 제외: 이 두 모듈형 솔루션은 점차 역사의 무대에서 사라졌으며 특정 기능은 더 이상 자세히 논의되지 않습니다.
  • "슬래시 앤 번" 시대의 남은 요구 사항을 해결하기 위해 AMD 및 CMD 모듈러 사양이 나왔습니다. 브라우저 측에서 비동기 모듈식 프로그래밍의 필요성, __other 핵심 원칙은 동적으로 스크립트를 로드하고 이벤트를 수신하여 모듈을 비동기적으로 로드하는 것입니다. __
  • AMD와 CMD의 가장 대표적인 두 작품은 각각 require.js와 sea.js에 해당합니다. ; 주요 차이점은 종속성 선언과 종속성에 있습니다. 로딩 타이밍, require.js는 기본적으로 선언될 때 실행됩니다. sea.js는 지연 로딩 및 주문형 사용을 권장하며 CMD 사양의 작성 방법도 언급할 가치가 있습니다. CommonJS와 매우 유사하며 약간만 수정하면 CommonJS에서 사용 가능합니다. 다음 사례를 참조하면 이해하기가 더 쉽습니다.

    // AMD
    define(['./a','./b'], function (moduleA, moduleB) {
      // 依赖前置
      moduleA.mehodA();
      console.log(moduleB.dataB);
      // 导出数据
      return {};
    });
     
    // CMD
    define(function (requie, exports, module) {
      // 依赖就近
      var moduleA = require('./a');
      moduleA.mehodA();     
    
      // 按需加载
      if (needModuleB) {
        var moduleB = requie('./b');
        moduleB.methodB();
      }
      // 导出数据
      exports = {};
    });
  • CommonJS

ty는 Node.js의 첫 번째 버전을 출시했습니다. 핵심 기능 중 하나로 CommonJS는 수년에 걸쳐 서버 측 시나리오에 적합합니다. 검사와 시간, 프론트 엔드 엔지니어링의 전폭적인 지원을 통해 CommonJS는 Node.js와 브라우저에서 널리 사용됩니다.

// Core Module
const cp = require('child_process');
// Npm Module
const axios = require('axios');
// Custom Module
const foo = require('./foo');

module.exports = { axios };
exports.foo = foo;

Specification

모듈(객체): 모듈 자체

내보내기(*) : 모듈의 내보낸 부분, 즉 노출된 내용

  • require(함수): 모듈을 로드하고, 대상 모듈의 내보낸 값을 가져오는 함수(기본 유형은 복사, 참조 유형은 얕은 복사) ), 내장 모듈, npm 모듈 및 사용자 정의 모듈

  • implementation

  • 1을 로드할 수 있습니다. 모듈 정의
  • 기본적으로 모든 .node .js .json 파일은 사양을 준수하는 모듈입니다. 2. 모듈 가져오기

  • 먼저 캐시(require.cache)에서 모듈을 먼저 읽고, 캐시가 누락된 경우 경로 분석이 수행된 후 다양한 유형의 모듈에 따라 처리됩니다.

내장 모듈

외부 모듈은 먼저 파일 주소 지정 및 위치 지정을 수행한 다음 컴파일 및 실행하고 마지막으로 해당 내보내기 값을 얻습니다.

    컴파일 프로세스 중에 Node는 얻은 JavaScript의 내용을 래핑합니다. 파일 헤드 및 테일 결과는 다음과 같습니다.
  • (function (exports, require, module, __filename, __dirname) {
        var circle = require('./circle.js');
        console.log('The area of a circle of radius 4 is ' + circle.area(4));
    });

    기능 요약

  • 동기화 모듈 선언 및 가져오기 논리를 실행하고 일부 복잡한 종속성 참조(예: 순환 종속성)를 분석할 때 주의하세요. , 더 나은 성능을 제공하고 메모리 사용량을 제한합니다.

모듈 모듈을 유연하게 수정할 수 있습니다. 높은 정확도, 일부 사용자 정의 요구 사항을 실현할 수 있습니다(예: 핫 업데이트, 모든 파일 형식에 대한 모듈 지원).

ES Module(推荐使用)

ES Module 是语言层面的模块化方案,由 ES 2015 提出,其规范与 CommonJS 比之 ,导出的值都可以看成是一个具备多个属性或者方法的对象,可以实现互相兼容;但写法上 ES Module 更简洁,与 Python 接近;

import fs from 'fs';
import color from 'color';
import service, { getArticles } from '../service'; 

export default service;
export const getArticles = getArticles;

主要差异在于:

  • ES Module 会对静态代码分析,即在代码编译时进行模块的加载,在运行时之前就已经确定了依赖关系(可解决循环引用的问题);

  • ES Module 关键字:import export 以及独有的 default  关键字,确定默认的导出值;

  • ES Module 中导入模块的属性或者方法是强绑定的,包括基础类型;

UMD

通过一层自执行函数来兼容各种模块化规范的写法,兼容 AMD / CMD / CommonJS 等模块化规范,贴上代码胜过千言万语,需要特别注意的是 ES Module 由于会对静态代码进行分析,故这种运行时的方案无法使用,此时通过 CommonJS 进行兼容;

(function (global, factory) {
  if (typeof exports === 'object') {   
    module.exports = factory();
  } else if (typeof define === 'function' && define.amd) {
    define(factory);
  } else {
    this.eventUtil = factory();
  }
})(this, function (exports) {
  // Define Module
  Object.defineProperty(exports, "__esModule", {
    value: true
  });
  exports.default = 42;
});

构建工具中的实现

为了在浏览器环境中运行模块化的代码,需要借助一些模块化打包的工具进行打包( 以 webpack 为例),定义了项目入口之后,会先快速地进行依赖的分析,然后将所有依赖的模块转换成浏览器兼容的对应模块化规范的实现;

模块化的基础

从上面的介绍中,我们已经对其规范和实现有了一定的了解;在浏览器中,要实现 CommonJS 规范,只需要实现 module / exports / require / global 这几个属性,由于浏览器中是无法访问文件系统的,因此 require 过程中的文件定位需要改造为加载对应的 JS 片段(webpack 采用的方式为通过函数传参实现依赖的引入)。具体实现可以参考:tiny-browser-require。

webpack 打包出来的代码快照如下,注意看注释中的时序;

(function (modules) {
  // The module cache
  var installedModules = {};
  // The require function
  function __webpack_require__(moduleId) {}
  return __webpack_require__(0); // ---> 0
})
({
  0: function (module, exports, __webpack_require__) {
    // Define module A
    var moduleB = __webpack_require__(1); // ---> 1
  },
  1: function (module, exports, __webpack_require__) {
    // Define module B
    exports = {}; // ---> 2
  }
});

实际上,ES Module 的处理同 CommonJS 相差无几,只是在定义模块和引入模块时会去处理 __esModule 标识,从而兼容其在语法上的差异。

异步和扩展

1、浏览器环境下,网络资源受到较大的限制,因此打包出来的文件如果体积巨大,对页面性能的损耗极大,因此需要对构建的目标文件进行拆分,同时模块也需要支持动态加载;

webpack 提供了两个方法 require.ensure() 和 import() (推荐使用)进行模块的动态加载,至于其中的原理,跟上面提及的 AMD & CMD 所见略同,import() 执行后返回一个 Promise 对象,其中所做的工作无非也是动态新增 script 标签,然后通过 onload / onerror 事件进一步处理。

2、由于 require 函数是完全自定义的,我们可以在模块化中实现更多的特性,比如通过修改 require.resolve 或 Module._extensions 扩展支持的文件类型,使得 css / .jsx / .vue / 图片等文件也能为模块化所使用;

附录:特性一览表

模块化规范 加载方式 加载时机 运行环境 备注
AMD 异步 运行时 浏览器
CMD 异步 运行时 浏览器
CommonJS 同步/异步 运行时 浏览器 / Node
ES Module 同步/异步 编译阶段 浏览器 / Node 通过 import() 实现异步加载

相关推荐:

javascript模块化编程(转载),javascript模块化

JavaScript模块化思想

위 내용은 Javascript 모듈성에 대한 자세한 소개의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

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