美文网首页
ES6模块的循环加载

ES6模块的循环加载

作者: 不看盛景不叙深情 | 来源:发表于2018-11-02 10:43 被阅读0次

ES6 处理“循环加载”与 CommonJS 有本质的不同。ES6 模块是动态引用,如果使用import从一个模块加载变量(即import foo from 'foo'),那些变量不会被缓存,而是成为一个指向被加载模块的引用,需要开发者自己保证,真正取值的时候能够取到值。

请看下面这个例子。

// a.mjs
import {bar} from './b';
console.log('a.mjs');
console.log(bar);
export let foo = 'foo';

// b.mjs
import {foo} from './a';
console.log('b.mjs');
console.log(foo);
export let bar = 'bar';

上面代码中,a.mjs加载b.mjs,b.mjs又加载a.mjs,构成循环加载。执行a.mjs,结果如下。

$ node --experimental-modules a.mjs
b.mjs
ReferenceError: foo is not defined

上面代码中,执行a.mjs以后会报错,foo变量未定义,这是为什么?

让我们一行行来看,ES6 循环加载是怎么处理的。首先,执行a.mjs以后,引擎发现它加载了b.mjs,因此会优先执行b.mjs,然后再执行a.mjs。接着,执行b.mjs的时候,已知它从a.mjs输入了foo接口,这时不会去执行a.mjs,而是认为这个接口已经存在了,继续往下执行。执行到第三行console.log(foo)的时候,才发现这个接口根本没定义,因此报错。

解决这个问题的方法,就是让b.mjs运行的时候,foo已经有定义了。这可以通过将foo写成函数来解决。

// a.mjs
import {bar} from './b';
console.log('a.mjs');
console.log(bar());
function foo() { return 'foo' }
export {foo};

// b.mjs
import {foo} from './a';
console.log('b.mjs');
console.log(foo());
function bar() { return 'bar' }
export {bar};
这时再执行a.mjs就可以得到预期结果。

$ node --experimental-modules a.mjs
b.mjs
foo
a.mjs
bar

这是因为函数具有提升作用,在执行import {bar} from './b'时,函数foo就已经有定义了,所以b.mjs加载的时候不会报错。这也意味着,如果把函数foo改写成函数表达式,也会报错。

// a.mjs
import {bar} from './b';
console.log('a.mjs');
console.log(bar());
const foo = () => 'foo';
export {foo};

相关文章

  • ES6模块的循环加载

    ES6 处理“循环加载”与 CommonJS 有本质的不同。ES6 模块是动态引用,如果使用import从一个模块...

  • 2.js模块化进阶

    如何在浏览器和 Node 之中加载 ES6 模块实际开发中经常遇到的一些问题(比如循环加载) 1.1.ES6 模块...

  • 关于JS模块化时循环加载的那些事儿(二)

    关于JS模块化时循环加载的那些事儿(二) 上一篇文章中介绍了ES6和CommonJS语法分别对于循环加载时的处理情...

  • 代码模块化

    2 ES6模块 ES6模块基于文件,一个文件就是一个模块。ES6模块支持异步模块加载。关键字:import和exp...

  • Module 的加载实现

    本章介绍如何在浏览器和 Node 之中加载 ES6模块,以及实际开发中经常遇到的一些问题(比如循环加载) 一、浏览...

  • ES6 模块与 CommonJS 模块的差异

    讨论 Node.js 加载 ES6 模块之前,必须了解 ES6 模块与 CommonJS 模块完全不同。impor...

  • 未来的模块机制

    概览 ES6实现了新的模块机制。在通过模块系统加载时,ES6会将文件当作独立的模块处理。每个模块都可以导入其它模块...

  • AMD、CMD、CommonJs、ES6的对比

    一、CommonJS 和 ES6 区别: 1.CommonJS 模块是运行时加载,ES6 模块是编译时输出接口。...

  • 第4章 ES6模块化

    目标 模块化系统演进 ES6模块化实现 模块化概述 在 ES6 之前,社区制定了一些模块加载方案,最主要的有 Co...

  • 第4章 ES6模块化

    目标 模块化系统演进 ES6模块化实现 模块化概述 在 ES6 之前,社区制定了一些模块加载方案,最主要的有 Co...

网友评论

      本文标题:ES6模块的循环加载

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