美文网首页
CommonJs和ES6的区别

CommonJs和ES6的区别

作者: PoWerfulHeart | 来源:发表于2023-07-12 20:51 被阅读0次

    CommonJs

    运行时加载(动态加载),相当于module.exports的那一刻进行了值拷贝,其实就是是给 module.exports 赋予了一个新的对象,拷贝的对象里每个key和每个value和module.exports对应
    因为是动态语法,所以可以写在判断里

    获取module.exports值的改变

    第一种方式

    我们知道module.exports实际上是执行了值拷贝,并且新对象的key和value与module.exports对应,那么对于引用类型的value而言,他们指向的都是同一个堆地址,当然可以动态获取

    //b.js
    const obj = {
        b: 1,
    };
    
    module.exports = {
        obj
    };
    
    setTimeout(() => {
        obj.b = 2;
    });
    
    //a.js
    const {
        obj,
    } = require("./b.js");
    
    console.log(obj.b);
    
    setTimeout(() => {
        console.log(obj.b);
    }, 1000);
    
    //node a.js
    //1
    //2
    

    翻译一下

    //b.js
      let obj = {
          b: 1
      };
    
      const myModule = {
          exports: {}
      }
    
      myModule.exports = {
          obj
      }
    
      setTimeout(() => {
          obj.b = 2;
      });
    
    //a.js
      const { obj: copyObj } = myModule.exports;
    
      console.log(copyObj.b);    //1
    
      setTimeout(() => {
           console.log(copyObj.b);   //2
      }, 1000);
    
      //const b = require('./b');
      //obj对象直接赋值给了新对象copyObj,两个对象指向同一个堆地址
      //这时候改变obj.b(两个对象仍然指向同一个堆地址),结果自然会改变
    

    第二种方式

    利用函数动态获取

    //b.js
    let b = 1
    
    module.exports = {
        getB: () => b
    };
    
    setTimeout(() => {
        b = 2;
    }, 500);
    
    //a.js
    const {
        getB
    } = require("./b.js");
    
    console.log(getB());
    
    setTimeout(() => {
        console.log(getB());
    }, 1000);
    
    //node a.js
    //1
    //2
    

    多次require同一个模块

    第一次require模块时会缓存其执行结果,当后面再require模块时不会重复执行模块代码,而是读取缓存并直接拷贝当前该模块已经module.exports的值

    //b.js
    module.exports.b = 1;
    const A = require('./a');
    console.log(A.a);
    module.exports.b = 2;
    
    //a.js
    module.exports.a = 1;
    const B = require('./b');
    console.log(B.b);
    module.exports.a = 2;
    
    //node a.js
    //执行b模块时,b 中想引入 a 模块的时候,因为 node 之前已经加载过 a 模块了,所以它不会再去重复执行 a 模块,而是直接拷贝一份{a: 1},所以A.a = 1
    //1
    //执行到a的打印时,b中的module.exports.b= 2修改了之前的导出,所以B.b = 2
    //2
    

    因为缓存机制,出现循环依赖时才不会出现无限循环调用的情况

    ES6

    编译时加载,也就是静态加载,相当于建立了动态绑定关系,当使用某个值时通过绑定关系,可以取到模块内部实时的值
    import是静态执行,所以不能使用表达式和变量,这些只有在运行时才能得到结果的语法结构

    import和export

    import在执行时会优先执行,export会“变量提升”

    // b.js
    export const b = 1;
    import * as a from "./a";
    console.log(a);
    
    // a.js
    import { b } from "./b";
    console.log("a.js");
    export const a = 1;
    export const A = () => {
       console.log("A");
    };
    export function AA() {
       console.log("AA");
    }
    
    //执行结果
    // { a: undefined, A: undefined, AA: [Function: AA] } AA是函数申明,会被提取到顶部,所以不是undefined,而函数表达式会和变量声明一样,只提升A,赋值操作要等到代码执行到具体位置,所以为undefined
    

    多次import同一个模块

    ES6 不会再去执行重复加载的模块,又由于 ES6 动态输出绑定的特性,能保证 ES6 在任何时候都能获取其它模块当前的最新值。

    // b.js
    import { a } from './a';
    export const b = '1';
    console.log(a);
    setTimeout(() => {
     console.log(a);
    })
    
    // a.js
    import { b } from './b';
    console.log(b);
    export const a = 2;
    
    //执行结果
    // undefined
    // 1
    // 2
    

    相关文章

      网友评论

          本文标题:CommonJs和ES6的区别

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