每一个导入的js模块都是活的, 每一次访问该模块的变量或者函数都是最新的, 这个是原生ES6模块 与AMD和CMD的区别之一,以下代码修改自#_imports-are-read-only-views-on-exports
运行下面代码
//lib.js export let counter = 3; export function incCounter() { counter++; } export function setCounter(value) { counter = value; } //main.js import { counter, incCounter ,setCounter} from './lib'; // The imported value `counter` is live console.log(counter); // 3 incCounter(); console.log(counter); // 4 setCounter(0); console.log(counter); // 0
在main.js中, counter一直指向lib.js中的局部变量counter, 按照JS的尿性, 像数字或者字符串类型或者布尔值的原始值要被复制, 而不是赋址;
循环依赖的问题:
NodeJS的循环依赖是这么处理的:;
循环依赖是JS模块化带来的问题, 在浏览器端, 使用RequireJS测试模块化, 比如有一个文件file0.js依赖于file1.js, 而file1.js又依赖于file0.js, 那么file0.js和file1.js到底谁先执行?
运行下面代码
//index.html <!DOCTYPE html> <html> <head> <title></title> <meta charset="utf-8"/> </head> <body> <script data-main="cyclic" src="https://cdn.bootcss.com/require.js/2.2.0/require.min.js"></script> <script> //cyclic.js require(["file0"], function(file0) { console.log(file0) }) //file0.js define(["file1"], function(file1) { console.log(file1) return { file0 : "file0" } }) //file1.js define(["file0"], function(file0) { console.log(file0); return { file1 : "file1" } }) </script> </body> </html>
在控制台的依次输出为:
运行下面代码
undefined
Object { file1: "file1" }
Object { file0: "file0" }
在执行file1.js的时候file0.js还没执行完, 所以输出了undefined, 这种输出结果和NodeJS输出的情况是一样的;
然后我又使用了司徒大神的mass-framework框架试了一下, 司徒大神的框架直接提示我: "模块与之前的某些模块存在循环依赖", 这样还比较好点, requireJS对于循环依赖是直接执行循环依赖的模块, 会导致在开发的时候给自己挖坑....;
接下来我又在babel-node下进行测试:下面是几个测试,可以无视:
我使用ES6的模块试一试, 只要每一个模块被引用, 无论模块是否执行完毕, 该模块的export已经被导出了, 如果导出的是函数:
运行下面代码
//cyclic.js import fn0 from "./file0"; fn0(); //file0.js import fn1 from "./file1"; fn1(); console.log("file0.js runs"); export default function() {console.log("file0 export runs")} //file1.js import fn0 from "./file0"; fn0(); console.log("file1.js runs"); export default function() {console.log("file1 export runs")}
如果导出的是字符串:
运行下面代码
//cyclic.js import str from "./file0"; console.log(str); //file0.js import str1 from "./file1"; console.log(str1) console.log("file0.js runs"); export default "str0"; //file1.js import str0 from "./file0"; console.log(str0) console.log("file1.js runs"); export default "str1";
如果导出的是对象:
那么第一行会先输出一个初始值{},在最后等待file0.js和file1.js执行完毕以后, 才输出file0.js导出的对象;
如果是数组:
那么第一行会输出一个被静态分析过的初始值undefined,在最后等待file0.js和file1.js执行完毕以后, 才输出file0.js导出的对象;
如果是布尔值:
那么第一行会输出一个被静态分析过的初始值undefined,在最后等待file0.js和file1.js执行完毕以后, 才输出file0.js导出的布尔值;
为什么会这样呢? 我好像在这边找到了答案: ,ES6的import和export被提前到js的最顶层, 在函数或者对象,或者基本值被导出去的时候提前被静态分析过,参考: ,
结论:用ES6的export导出数据接口的时候, 最好统一用函数, 避免在循环依赖的时候, 因为JS会把不同类型的对象静态解析成不同的初始值;
浏览器兼容:
chrome浏览器目前不支持import,和export;
火狐的支持也有限, 比chrome好;