2.2 ES Module模块化的原理

ES Module的原理

ES Module和CommonJS的区别

一、CommonJS模块加载js文件的过程是运行时加载的,并且是同步的:

  • 运行时加载意味着是js引擎在执行js代码的过程中加载 模块;
  • 同步的就意味着一个文件没有加载结束之前,后面的代码都不会执行;
console.log("main代码执行");

const flag = true;
if (flag) {
  // 同步加载foo文件,并且执行一次内部的代码
  const foo = require('./foo');
  console.log("if语句继续执行");
}

二、CommonJS通过module.exports导出的是一个对象:

  • 导出的是一个对象意味着可以将这个对象的引用在其他模块中赋值给其他变量;
  • 但是最终他们指向的都是同一个对象,那么一个变量修改了对象的属性,所有的地方都会被修改;

三、ES Module加载js文件的过程是编译(解析)时加载的,并且是异步的:

  • 编译时(解析)时加载,意味着import不能和运行时相关的内容放在一起使用:

    • 比如from后面的路径需要动态获取;
    • 比如不能将import放到if等语句的代码块中;
    • 所以我们有时候也称ES Module是静态解析的,而不是动态或者运行时解析的;
  • 异步的意味着:JS引擎在遇到import时会去获取这个js文件,但是这个获取的过程是异步的,并不会阻塞主线程继续执行;

    • 也就是说设置了 type=module 的代码,相当于在script标签上也加上了 async 属性;
    • 如果我们后面有普通的script标签以及对应的代码,那么ES Module对应的js文件和代码不会阻塞它们的执行;
<script src="main.js" type="module"></script>
<!-- 这个js文件的代码不会被阻塞执行 -->
<script src="index.js"></script>

四、ES Module通过export导出的是变量本身的引用:

  • export在导出一个变量时,js引擎会解析这个语法,并且创建模块环境记录(module environment record);
  • 模块环境记录会和变量进行 绑定(binding),并且这个绑定是实时的;
  • 而在导入的地方,我们是可以实时的获取到绑定的最新值的;

所以我们下面的代码是成立的:

bar.js文件中修改

let name = 'coderwhy';

setTimeout(() => {
  name = "湖人总冠军";
}, 1000);

setTimeout(() => {
  console.log(name);
}, 2000);

export {
  name
}

main.js文件中获取

import { name } from './modules/bar.js';

console.log(name);

// bar中修改, main中验证
setTimeout(() => {
  console.log(name);
}, 2000);

但是,下面的代码是不成立的:main.js中修改

import { name } from './modules/bar.js';

console.log(name);

// main中修改, bar中验证
setTimeout(() => {
  name = 'kobe';
}, 1000);

导入的变量不可以被修改

思考:如果bar.js中导出的是一个对象,那么main.js中是否可以修改对象中的属性呢?

  • 答案是可以的,因为他们指向同一块内存空间;(自己编写代码验证,这里不再给出)
  • 因为他们指向同一块内存空间;(自己编写代码验证,这里不再给出)

原文链接:彻底掌握前端模块化

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值