深刻探究ES6之模块系统

在上一篇《前端模块化,AMD和CMD的区别总结》中,介绍了commonJS规范下衍生出来的AMD和CMD。多年来,前端的js代码大都是以这种方式组织起来(再早连这个都没有。。。),可是从语言设计自己的层面上讲,官方一直没有设计出javascript的模块系统,直到。。。ES6的正式发布!javascript

能够说ES6的正式发布(讨论了十年)是前端界翘首以盼众望所归的事,它是javascript被建立以来最重要的更新之一。而其中最重要的就是JS模块化的定义,从原生语法上支持了导入与导出模块,咱们终于再也不须要使用一些库(Requirejs、Seajs等)来模仿模块化了。前端

本文不想过多介绍如何使用ES6模块的语法(好比import和export的规范),由于网络上关于这方面的介绍已经不少了,如今来讲点不太常被说起可是对理解有很重要的东西。java

“模块”是自动运行在严格模式下而且没有办法退出运行的JavaScript代码。模块有三个比较显著的特性:git

一、在模块顶部建立的变量不会自动被添加到全局做用域(好比windows下),访问模块的变量必须经过导出的方式。

二、在模块顶部this的值是undefined。

三、模块不支持HTML的代码注释。

以上也是ES6模块区别于传统模块系统很重要的三点,并且ES6模块系统与传统模块系统更显著的一个区别是:github

四、ES6的模块系统是静态解析的

举例:windows

if(Math.random()){
    import name from './example.js'   // 抛出错误
}
-------------------------------------------------
let name = 'js'
if(Math.random()){
    export {name}   // 抛出错误
}
复制代码

import和export不能在条件语句或任何动态方式中使用,缘由是要让JavaScript引擎静态地肯定哪些模块能够导出。
若是使用过RequireJS或者SeaJS的开发者应该深有体会,它们可没有这样的限制。 因为ES6模块的静态性,致使了一个怪异甚至让人困惑之处,先看一个例子:bash

//a.js
let name = 'ajs';
let setName = fuction(newName) {
    name = newName;
}
export {name, setName}

//b.js
import {name, setName} from './a.js';
console.log(name)   // 'ajs'
name = 'bjs'    // 抛出错误
setName('cjs')
console.log(name)   // 'cjs'
复制代码

b.js只是简单的引用了a.js中的值,而不能改变a.js中的值,当调用setName('cjs')时会回到a.js中去执行,并将其中的name设置为'cjs'。这说明ES6模块输出的是值的引用,与CommonJS(输出的是值的拷贝)彻底不一样。网络

至于将ES6模块系统设计成静态的缘由,你们能够参考这篇文章Static module resolution。其中原理较为深奥,我的认为能够不求甚解。dom

PS:动态import(不是ES6的内容)

凡事有利就有弊,静态性的模块系统在带来一系列好处的同时,也限制了开发者对于项目灵活性的掌控。好比在某些条件语句或是用户点击触发的操做里面,动态(或者说按需)导入模块的要求就变得很迫切。不过还好,如今动态导入的提案已经存在于TC39第三阶段了。模块化

你能够这样使用:

if(Math.random()){
    import('./example.js').then((M)=>{
        let Mod = M.default
        // TODO
    }) 
}
或者
if(Math.random()){
    import('./example.js').then(({setName})=>{
        setName('Dynamic')
        // TODO
    }) 
}
甚至是这样
const locale = 'en';
import(`./utils_${locale}.js`).then(
  (utils)=>{
    console.log('utils', utils);
    utils.default();
  }
);
复制代码

·你能够在延迟加载、条件加载和用户操做的情景下使用动态导入
·动态import()能够在脚本的任何地方使用
·import()可以传递字符串,你能够根据你的需求构造匹配符

欢迎你们积极留言指出问题及不足,我会及时修改文章内容,咱们也能够一块儿探讨一些技术问题,道理越讲越清楚。

相关文章
相关标签/搜索