zoukankan      html  css  js  c++  java
  • commonjs和ES Module

    commonjs导出方法exports和module.exports的区别?

    commonjs实际导出的就是exports这个对象,可以把需要导出的变量、方法等绑定在exports这个对象上导出,例如:

    //a.js
    exports.name = '阿明先森'
    
    console.log(require('./a.js') );
    

    打印:

    {
        "name": "amingxiansen"
    }
    

    小结:所以用exports导出的都是对象,导出内容包含在对象里。

    module.exportsexports具有相同的引用。module.exports可以直接导出函数、变量等。例如:

    module.exports  = '阿明先森'
    

    打印:

    小结:当然想要导出对象也没问题:module.exports = {};相比exports,更灵活也更容易理解,推荐使用module.exports进行导出。

    如果使用exports = {name: '阿明先森'}导出对象会怎么样呢?
    打印:

    打印为空,原因是exports是导出函数传入的参数,exports = {}相当于在函数里面重新声明了一个exports变量,和原来的参数脱离了关系,所以打印出来的是原来的参数,为空。
    举个例子:

    const myExports  = {}
    function Test(myExports) {
      myExports  = {name: 'amingxiansen'} //这里的myExports与参数脱离了关系,相当于在局部声明了let Exports
    }
    console.log(Test(myExports)) // {}
    

    小结: 所以使用exports导出,必须要把导出内容绑定在exports上,作为它的一个属性导出。

    module.exports ={
        name:'amingxiansen'
    }
    exports.name = 'alien' // 此时 `exports.name` 是无效的
    

    此时exports会被module.exports覆盖
    小结: module.exports优先级高于exports,应该避免两种导出混合使用。

    commonjs实现原理?

    在编译过程中,commonjs经过了收尾的包装,像下面这样:

    (function(exports,require,module,__filename,__dirname){
       const sayName = require('./hello.js')
        module.exports = function say(){
            return {
                name:sayName(),
                author:'我不是外星人'
            }
        }
    })
    

    Commonjs 规范模块中,会形成一个包装函数,我们写的代码将作为包装函数的执行上下文,使用的 require ,exports ,module 本质上是通过形参的方式传递到包装函数中的。

    require加载原理?

    每个文件都是一个module,module上除了有模块的基本信息之外,还会有个loaded代表模块是否已经加载过。二次加载会直接使用缓存中的数据。
    以nodejs为例,整个系统运行之后,会用 Module 缓存每一个模块加载的信息。
    加入缓存的顺序是:先加入缓存再执行
    require源码:

     // id 为路径标识符
    function require(id) {
       /* 查找  Module 上有没有已经加载的 js  对象*/
       const  cachedModule = Module._cache[id]
       
       /* 如果已经加载了那么直接取走缓存的 exports 对象  */
      if(cachedModule){
        return cachedModule.exports
      }
     
      /* 创建当前模块的 module  */
      const module = { exports: {} ,loaded: false , ...}
    
      /* 将 module 缓存到  Module 的缓存属性中,路径标识符作为 id */  
      Module._cache[id] = module
      /* 加载文件 */
      runInThisContext(wrapper('module.exports = "123"'))(module.exports, require, module, __filename, __dirname)
      /* 加载完成 *//
      module.loaded = true 
      /* 返回值 */
      return module.exports
    }
    
    

    ES module

    对模块化module的支持是从ES6以后开始的。ES module导入导出使用 importexport。可以导出函数、变量、对象等。
    export default //默认导出 ===> import temp from './a.js'
    export {a, b, c} ===> import {a, b, c} from './a.js'
    也可以混合导入导出。

    es module的特性

    1. ES6 module 的引入和导出是静态的,import 会自动提升到代码的顶层 ,import , export 不能放在块级作用域或条件语句中。
      import命令会被 JavaScript 引擎静态分析,在编译时就引入模块代码,而不是在代码运行时加载,所以无法实现条件加载。也正因为这个,使得静态分析成为可能。
    2. ES6 module 和 Common.js 一样,对于相同的 js 文件,会保存静态属性。
      但是与 Common.js 不同的是 ,CommonJS 模块同步加载并执行模块文件,ES6 模块提前加载并执行模块文件,ES6 模块在预处理阶段分析模块依赖,在执行阶段执行模块,两个阶段都采用深度优先遍历,执行顺序是子 -> 父。
    3. es module import导入的是值的引用,但是read only的,直接修改会报错,可以通过方法修改;commonjs require导入的是属性的copy,可以更改导入属性。

    总结

    Commonjs 特性总结

    • CommonJS 模块由 JS 运行时实现。
    • CommonJs 是单个值导出,本质上导出的就是 exports 属性。
    • CommonJS 是可以动态加载的,对每一个加载都存在缓存,可以有效的解决循环引用问题。
    • CommonJS 模块同步加载并执行模块文件。

    ES Module特性总结

    • ES6 Module 静态的,不能放在块级作用域内,代码发生在编译时。
    • ES6 Module 的值是动态绑定的,可以通过导出方法修改,可以直接访问修改结果。
    • ES6 Module 可以导出多个属性和方法,可以单个导入导出,混合导入导出。
    • ES6 模块提前加载并执行模块文件,
    • ES6 Module 的特性可以很容易实现 Tree Shaking 和 Code Splitting。
    四体不勤 五谷不分 文不能测字 武不能防身
  • 相关阅读:
    TensorFlow分布式在Amazon AWS上运行
    在C++中加载TorchScript模型
    java 在 linux 持续运行 并不让其输出日志
    reactor.core.Exceptions$OverflowException: Could not emit tick 1 due to lack of requests (interval doesn't support small downstream requests that replenish slower than the ticks)
    https://gitee.com/createmaker/webflux-r2dbc-demo-pri
    清晨与暮霭 : 清晨,我睁开惺忪得眼睛,望向初升的朝阳,感受温暖. 暮霭,聆听风的私语,感受万籁俱寂.
    https://gitee.com/createmaker/eventbus-demo
    Constructor(构造方法) -> @Autowired(依赖注入) -> @PostConstruct(注释的方法)
    只是习惯,改掉就好,只是不习惯,习惯了就好
    从游戏角度了解RxJava
  • 原文地址:https://www.cnblogs.com/amingxiansen/p/15319602.html
Copyright © 2011-2022 走看看