美文网首页前端学习
前端基础整理 | require / exports / imp

前端基础整理 | require / exports / imp

作者: 格致匠心 | 来源:发表于2019-07-18 00:13 被阅读0次

    一、 模块规范

    一句话总结:CommonJs用于服务端Node.js中,AMD和CMD是针对客户端的规范,为了不让引入依赖阻塞了代码进行,使用了异步加载模块。

    1. CommonJs:

    • 适用区域:用于服务端。
    • 导入:require
    • 导出:module.exportsexports
    • exports与module.exports
      exportsmodule.exports的引用,var exports = module.exports = {};,而最终导出的是仍然是module.exports,因此,倘若更改exports的指向,最终返回的仍然是module.exports
    • 用法:

    module.exports 基础用法

    /* export.js */
    const a = 1
    module.exports = a
    /* import.js */
    var a = require('./export')
    // a = 1
    

    exports 基础用法

    /* export.js */
    exports.a = 1 // 不能改变引用, exports = {a:1}🙅
    /* import.js */
    var a = require('./export')
    // a = {a:1}
    

    可以使用es6的特性 - 解构赋值

    /* export.js */
    exports.a = 1
    /* import.js */
    var {a} = require('./export')
    // a = 1
    
    • 为什么不适用于客户端?
      同步引用不适用于客户端场景
    var _ = require('./loadsh')
    _.map([1,2,3], square)
    

    如上面👆所示,如果loadsh这个库由于网络原因加载得很慢的话,那么它便阻塞了后面代码的运行,这样对用户体验牺牲很大。
    这时候AMD就有了诞生的需求了。

    2. AMD:

    AMD是”Asynchronous Module Definition”的缩写,意思就是”异步模块定义”。它采用异步方式加载模块,模块的加载不影响它后面语句的运行。所有依赖这个模块的语句,都定义在一个回调函数中,等到加载完成之后,这个回调函数才会运行。

    • 使用define定义模块:
    // id:模块名(可选),dependencies:依赖库(可选),factory工厂方法,返回一个模版函数
    define(id?, [dependencies?], factory)
    // demo
    define(['Lib'], function(Lib){
      function foo(){
        Lib.doSomething();
      }
      return {
        foo : foo
      };
    });
    
    • 使用require加载模块,因为是回调执行,所以不阻塞啦。
    // module:加载的模块数组, callback:加载成功后再执行的回调函数
    require([module], callback);
    // demo
    require([loadsh], loadsh.map([1,2,3],square))
    

    目前,主要有两个Javascript库实现了AMD规范:require.jscurl.js

    3. CMD:

    CMD (Common Module Definition), 是seajs推崇的规范。它与AMD最大的区别是它推崇依赖就近。

    • 同样,CMD使用define定义模块
    // id:模块名(可选),dependencies:依赖库(可选),factory工厂方法,返回一个模版函数
    define(id?, [dependencies?], factory)
    // 不同点:它可以在工厂函数中导出导入(也是通常的做法),也是它推崇的导出导入方式
    define(function(require, exports, module) {
    // 模块代码
      var $ = require('jquery.js')
      $('div').addClass('active');
    });
    
    • 用use加载模块
    // 加载模块
    seajs.use(['myModule.js'], function(my){
    });
    
    • 与AMD的区别:
      最明显的区别就是在模块定义时对依赖的处理不同
      1、AMD推崇依赖前置,在定义模块的时候就要声明其依赖的模块
      2、CMD推崇就近依赖,只有在用到某个模块的时候再去require
      这种区别各有优劣,只是语法上的差距,而且requireJS和SeaJS都支持对方的写法
      AMD和CMD最大的区别是对依赖模块的执行时机处理不同,注意不是加载的时机或者方式不同。
      AMD在加载模块完成后就会执行改模块,所有模块都加载执行完后会进入require的回调函数,执行主逻辑,这样的效果就是依赖模块的执行顺序和书写顺序不一定一致,看网络速度,哪个先下载下来,哪个先执行,但是主逻辑一定在所有依赖加载完成后才执行
      CMD加载完某个依赖模块后并不执行,只是下载而已,在所有依赖模块加载完成后进入主逻辑,遇到require语句的时候才执行对应的模块,这样模块的执行顺序和书写顺序是完全一致的

    二. ES6

    这里主要介绍:

    • ES6的import和export和export default的基本用法
    • ES6和CommonJs的混用

    1. 基本用法

    /* export.js */
    export const a = 1
    /* import.js */
    import { a } from './export'
    // a = 1
    

    经过babel的转换。可以看到转化为exports->require,并且给exports添加了一个__esModule的属性。

    /* export.js */
    "use strict";
    Object.defineProperty(exports, "__esModule", {
      value: true
    });
    exports.a = void 0;
    const a = 1;
    exports.a = a;
    /* import.js */
    "use strict";
    var _export = require("./export");
    console.log(_export.a);
    

    export default

    // export.js
    const b = 2
    export default b
    // import.js
    import b from './export'
    console.log(b)
    

    通过babel转化,使用exports.default进行导出。

    /* export.js */
    Object.defineProperty(exports, "__esModule", {
      value: true
    });
    exports.default = void 0;
    const b = 2;
    var _default = b;
    exports.default = _default;
    

    ⚠️注意:不能认为 import { b } from './export' 是用了解构赋值。当执行以下代码是不行的。import 语句中的"解构赋值"并不是解构赋值,而是 named imports。

    // import.js
    import { {a} } from './export' // 语法错误
    console.log(a)
    // export.js
    export const b = { a: 1 }
    

    named imports,语法上和解构赋值很像,但还是有所差别,比如下面的例子。

    import { b as a } from './export' // 解构赋值中不能用 as
    

    因此还是得老老实实把值接下来,然后再去处理。或者你可以和CommonJs混用来达到类似解构赋值的效果。

    2. 与CommonJs混用

    由于babel解析的时候也是解析成exports->require形式的,因此可以和commonJs混用。

    • import.js / require - export.js / export
    // import.js
    var { b } = require('./export').default
    console.log(b)
    // export.js
    export default {
      b: 2
    }
    
    • import.js / import - export.js / exports
    // import.js
    import { a } from './export'
    console.log(a)
    // export.js
    module.exports = {
      a: 1
    }
    

    相关文章

      网友评论

        本文标题:前端基础整理 | require / exports / imp

        本文链接:https://www.haomeiwen.com/subject/abkhlctx.html