• JS JavaScript模块化(ES Module/CommonJS/AMD/CMD)


    前言

    前端开发中,起初只要在script标签中嵌入几十上百行代码就能实现一些基本的交互效果,后来js得到重视,应用也广泛起来了,

    jQuery,Ajax,Node.Js,MVC,MVVM等的助力也使得前端开发得到重视,也使得前端项目越来越复杂,

    然而,JavaScript却没有为组织代码提供任何明显帮助,甚至没有类的概念,更不用说模块(module)了,那么什么是模块呢?

    一个模块就是实现特定功能的文件,有了模块,我们就可以更方便地使用别人的代码,想要什么功能,就加载什么模块。

    一、AMD 规范

    AMD 是 RequireJS 在推广过程中对模块定义的规范化产出。

    模块将被异步加载,模块加载不影响后面语句的运行。

    所有依赖某些模块的语句均放置在回调函数中。

    用法:

    • 定义模块:define(id?, dependencies?, factory)
    • 加载模块:require([module], factory)
    // a.js
    // 依赖有三个默认的,即"require", "exports", "module"。顺序个数均可视情况
    // 如果忽略则factory默认此三个传入参数
    // id一般是不传的,默认是文件名
    define(["b", "require", "exports"], function(b, require, exports) {
        console.log("a.js执行");
        console.log(b);
    // 暴露api可以使用exports、module.exports、return
        exports.a = function() {
            return require("b");
        }
    })
    // b.js
    define(function() {
        console.log('b.js执行');
        console.log(require);
        console.log(exports);
        console.log(module);
        return 'b';
    })
    // index.js
    // 支持Modules/Wrappings写法,注意dependencies得是空的,且factory参数不可空
    define(function(require, exports, module) {
        console.log('index.js执行');
        var a = require('a');
        var b = require('b');
    })
    // index.js
    require(['a', 'b'], function(a, b) {
        console.log('index.js执行');
    })

    二、CMD 规范

    CMD 是 SeaJS 在推广过程中对模块定义的规范化产出。

    在 CMD 规范中,一个模块就是一个文件。

    用法:

    • 定义模块:define(factory)
    / require, exports, module参数顺序不可乱
    // 暴露api方法可以使用exports、module.exports、return
    // 与requirejs不同的是,若是未暴露,则返回{},requirejs返回undefined
    define(function(require, exports, module) {
        console.log('a.js执行');
        console.log(require);
        console.log(exports);
        console.log(module);
    })
    // b.js
    // 
    define(function(require, module, exports) {
        console.log('b.js执行');
        console.log(require);
        console.log(exports);
        console.log(module);
    })
    // index.js
    define(function(require) {
        var a = require('a');
        var b = require('b');
        console.log(a);
        console.log(b);
    })

    三、CommonJs 规范

    CommonJs 是服务器端模块的规范。

    Node.js 采用了这个规范。Node.JS首先采用了js模块化的概念。

    根据 CommonJs 规范,一个单独的文件就是一个模块。每一个模块都是一个单独的作用域,也就是说,在该模块内部定义的变量,无法被其他模块读取,除非定义为 global 对象的属性。

    用法:

    • 输出模块:module.exports
    • 加载模块:require
    // 导出使用module.exports,也可以exports。exports指向module.exports;即exports = module.exports
    // 就是在此对象上挂属性
    // commonjs
    module.exports.add = function add(params) {
        return ++params;
    }
    exports.sub = function sub(params) {
        return --params;
    }
    
    // 加载模块使用require('xxx')。相对、绝对路径均可。默认引用js,可以不写.js后缀
    // index.js
    var common = require('./commonjs');
    console.log(common.sub(1));
    console.log(common.add(1));

    四、ES Module

    ES6 在语言标准的层面上,实现了模块功能,成为浏览器和服务器通用的模块解决方案,完全可以取代 CommonJS 和 AMD 规范。

    基本特点:

    • 每一个模块只加载一次, 每一个JS只执行一次, 如果下次再去加载同目录下同文件,直接从内存中读取;
    • 每一个模块内声明的变量都是局部变量, 不会污染全局作用域;
    • 模块内部的变量或者函数可以通过export导出;
    • 一个模块可以导入别的模块

    用法:

    • 输出模块:export
    • 加载模块:import 
    // module
    export function fn1(){
        return  "这是 fn1";
    }
    
    export function fn2(){
        return "这是 fn2" ;
    }
    
    // main.js
    //逐一加载
    import { fn1, fn2 } from './module';
    
    console.log( fn1());
    console.log( fn2());
    
    //整体加载
    import * as all from './module';
    
    console.log( all.fn1() );
    console.log( all.fn2() );

    动态加载模块:

    // 普通写法
    import('./module').then(({ a }) => {})
    // async、await
    const { a } = await import('./module');

    五、各模块之间的区别

    1、CommonJS 与 AMD/CMD 的差异

    • CommonJS:是同步加载(代码在本地,加载时间基本等于硬盘读取时间)。
    • AMD / CMD:是异步加载

    2、AMD 与 CMD 的差异

    • AMD是提前执行,CMD是延迟执行
    • AMD推荐依赖前置,CMD推荐依赖就近

    3、CommonJS 与 ES Module 的差异

    • CommonJS 模块是对象,是运行时加载,运行时才把模块挂载在 exports 之上(加载整个模块的所有),加载模块其实就是查找对象属性
    • ES Module 不是对象,是使用 export 显示指定输出,再通过 import 输入,此法为编译时加载
    • CommonJS 模块输出的是一个值的拷贝,ES6 模块输出的是值的引用。
    • CommonJS 模块是运行时加载,ES6 模块是编译时输出接口

    3、各模块用法上的区别

      详见各模块介绍...

    随笔整理自
      https://www.jianshu.com/p/da2ac9ad2960
    感谢博主分享!
  • 相关阅读:
    【移动安全基础篇】——30、class.dex文件格式讲解
    【移动安全基础篇】——29、Android源码定制添加反反调试机制
    【移动安全基础篇】——28、Apk加固
    【移动安全基础篇】——27、常用调试检测方法与过检测方法
    【移动安全基础篇】——26、两个简单app破解
    粒子特效优化
    android studio生成aar包
    AndroidManifest
    声音
    unity webview
  • 原文地址:https://www.cnblogs.com/gaosirs/p/10772675.html
Copyright © 2020-2023  润新知