为什么说JavaScript的模块是静态的?

本文详细解析了ES6模块技术中的export和import,重点在于导出的是名字和值,尤其是默认导出(default)的概念。模块系统是静态的,形成名字表和依赖树,执行阶段负责绑定值并执行顶层代码。
摘要由CSDN通过智能技术生成

不同于Nodejs的动态加载, ES6的模块技术确是静态的

导出什么东西?

我们首先思考一下, 我们在使用export去导出什么东西。我们导出的是名字(name)和值(value)。毕竟关键字, 那些加减乘除符号和一些括号符号之外, 名字和值就是你代码出现且有用的东西了。

//基础声明的name
export <let/const/var> x;
export function x(){};
export class x;
export {x, y, z ...};

//重命名
export {x as y, ...};
export {x as default, ...};

//导出其它模块的名字
export ... from ...;

关于名字很好处理, 将导出的名字放在一个符号表中, 当导入的时候从表中读取就可以了。

那么值(value)如何去处理, 值压根没有名字, 何谈导出,所以为了这一点JavaScript为导出的值去设计了一个特殊的名字叫做default。这样导出值就有了一个默认的名字叫做default, 于是你就可以导出这个值了。

于是你可以写出下面这种代码:

export default expression;

export default 2;
export default "hello, world";


//对象字面量也是一个值
export default {};

//匿名函数也是一个值
export default function() {};

导出语句与导入语句的处理逻辑

我们导出一个名字之后, 还需要使用它 比如

模块1
export let a = 1;

模块2
import a from "./xxx.js"
console.log(a + 1);

由于其他模块需要使用, 我们就需要为导出的名字绑定一个值, 所以export的处理逻辑为

  1. 在导出变量的文件形成一个模块表, 登记名字
  2. 为名字绑定一个值, 这是JavaScript执行期间的东西

可以使用JavaScript简单模拟一下:

let table = [];
table.push({name:a, value: 1});

对应的模块2的import处理逻辑为

  1. 添加对该模块的一个依赖, 这样我们就可以根据import形成模块依赖树, 找到跟模块, 然后加载了.
  2. 在当前模块环境(scope)声明一个名字

所以总结export/import就是:

  1. 根据export形成一个名字表
  2. 根据import形成一个依赖

所以说ES6的模块系统export/import完全是静态的, 因为根本就没有出现像a+1这样需要执行去代码.但是到了执行阶段就要做下面的事情:

  • 找到静态装载阶段的模块树, 并且遍历
  • 执行最顶层的代码
  1. 为名字绑定值, 包括为导出值绑定default这个特殊的名字
  2. 使用名字
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值