专栏名称: Lindz
前端工程师
目录
相关文章推荐
前端早读课  ·  【第3532期】错误页面演变史:如何让失误变 ... ·  13 小时前  
前端大全  ·  Cursor 内部工作原理 ·  昨天  
龙视新闻联播  ·  清凉在龙江丨四季皆可游 昼夜都精彩 ·  23 小时前  
龙视新闻联播  ·  清凉在龙江丨四季皆可游 昼夜都精彩 ·  23 小时前  
前端早读课  ·  【第3530期】像高手一样调试程序 ·  2 天前  
前端大全  ·  GitHub 第 10 ... ·  3 天前  
51好读  ›  专栏  ›  Lindz

深入理解 ES6 模块机制

Lindz  · 掘金  · 前端  · 2018-02-17 03:14

正文

请到「今天看啥」查看全文


然而在 ES6 模块中就不再是生成输出对象的拷贝,而是动态关联模块中的值。

// a.js
import { foo } from './b';
console.log(foo);
setTimeout(() => {
  console.log(foo);
  import('./b').then(({ foo }) => {
    console.log(foo);
  });
}, 1000);

// b.js
export let foo = 1;
setTimeout(() => {
  foo = 2;
}, 500);
// 执行:babel-node a.js
// 执行结果:
// 1
// 2
// 2

ES6 静态编译,CommonJS 运行时加载

关于第二点,ES6 模块编译时执行会导致有以下两个特点:

  1. import 命令会被 JavaScript 引擎静态分析,优先于模块内的其他内容执行。
  2. export 命令会有变量声明提前的效果。

import 优先执行:

从第一条来看,在文件中的任何位置引入 import 模块都会被提前到文件顶部。

// a.js
console.log('a.js')
import { foo } from './b';

// b.js
export let foo = 1;
console.log('b.js 先执行');

// 执行结果:
// b.js 先执行
// a.js

从执行结果我们可以很直观地看出,虽然 a 模块中 import 引入晚于 console.log('a'),但是它被 JS 引擎通过静态分析,提到模块执行的最前面,优于模块中的其他部分的执行。

由于 import 是静态执行,所以 import 具有提升效果即 import 命令在模块中的位置并不影响程序的输出。

export 变量声明提升:

正常的引入模块是没办法看出变量声明提升的特性,需要通过循环依赖加载才能看出。

// a.js
import { foo } from './b';
console.log('a.js');
export const bar = 1;
export const bar2 = () => {
  console.log('bar2');
}
export function bar3() {
  console.log('bar3');
}

// b.js
export let foo = 1;
import * as a from './a';
console.log(a);

// 执行结果:
// { bar: undefined, bar2: undefined, bar3: [Function: bar3] }
// a.js

从上面的例子可以很直观地看出,a 模块引用了 b 模块,b 模块也引用了 a 模块,export 声明的变量也是优于模块其它内容的执行的,但是具体对变量赋值需要等到执行到相应代码的时候。(当然函数声明和表达式声明不一样,这一点跟 JS 函数性质一样,这里就不过多解释)

好了,讲完了 ES6 模块和 CommonJS 模块的不同点之后,接下来就讲讲相同点:

模块不会重复执行

这个很好理解,无论是 ES6 模块还是 CommonJS 模块,当你重复引入某个相同的模块时,模块只会执行一次。







请到「今天看啥」查看全文