JavaScript模块规范
在任何一个大型应用中模块化是很常见的,与一些更传统的编程语言不同的是,JavaScript6之前还不支持原生的模块化;Javascript社区做了很多努力,在现有的运行环境中,实现"模块"的效果。通行的JavaScript模块规范主要有两种:CommonJS、AMD
CommonJS规范是服务器端Javascript模块规范(同步)
Node.js的模块系统,就是参照CommonJS规范实现的。NPM也遵循了commonJS定义的包规范,从而形成了一套完整的生态系统
AMD意思是"异步模块定义",是前端模块规范
RequireJS就是实现了AMD规范的
CommonJS module以服务器端为第一的原则发展,选择同步加载模块。它的模块是无需包装的,但它仅支持对象类型(objects)模块
AMD以浏览器为第一的原则发展,选择异步加载模块。它的模块支持对象、函数、构造器、字符串、JSON等各种类型的模块,因此在浏览器中它非常灵活
ES6模块的import和export用法总结
ES6之前已经出现了js模块加载的方案,最主要的是
commonjs 服务器 同步加载 如nodejs
AMD 浏览器 异步加载 如requirejs
ES6在语言规格的层面上,实现了模块功能,而且实现得相当简单
完全可以取代现有规范,成为浏览器和服务器通用的模块解决方案
运行时加载
CommonJS模块是对象,实质是整体加载模块(即加载fs的所有方法),生成一个对象,然后再从这个对象上面读取其中3个方法这种加载称为“运行时加载”,因为只有运行时才能得到这个对象
编译时加载
ES6模块不是对象,是通过export命令显式指定输出的代码,再通过import命令输入
的实质是从fs模块加载3个方法,其他方法不加载。这种加载称为“编译时加载”或者静态加载,即ES6可以在编译时确定模块的依赖关系,以及输入和输出的变量,效率更高
ES6模块主要有两个功能:export和import
export用于对外输出本模块(一个文件可以理解为一个模块)变量的接口
import用于在一个模块中加载另一个含有export接口的模块。
也就是说使用export命令定义了模块的对外接口以后,其他JS文件就可以通过import命令加载这个模块(文件)。如下图(假设a和b文件在同一目录下)
// a.js
var sex="boy";
var echo=function(value){
console.log(value)
}
export {sex,echo}
//通过向大括号中添加sex,echo变量并且export输出,就可以将对应变量值以sex、echo变量标识符形式暴露给其他文件而被读取到
1.export {sex,echo}
[不用] export default命令,为模块指定默认输出 其实只是输出一个叫做default的变量
(1)[只能默认输出单个,不能是对象]
var abc=function(){}
export default abc
import xx from './a.js'
xx()
(2)如果想在一条import语句中,同时输入默认方法和其他接口
var abc=function(){}
var cba=function(){}
var bac=function(){}
export default abc
export {cba}
import xx,{cba,bac} from './a.js'
xx() cba() bac()
// b.js
通过import获取a.js文件的内部变量,{}括号内的变量来自于a.js文件export出的变量标识符。
import {sex,echo} from "./a.js"
console.log(sex) // boy
echo(sex) // boy
1.import命令接受一对大括号,里面指定要从其他模块导入的变量名
大括号里面的变量名,必须与被导入模块(profile.js)对外接口的名称相同
import {sex,echo} from "./a.js"
2.除了指定加载某个输出值,还可以使用整体加载,即用星号(*)指定一个对象,所有输出值都加载在这个对象上面
import * as xx from './circle';
console.log('圆面积:' + xx.area(4));
以上是export与import的基本用法,再进行拓展学习
前面的例子可以看出,b.js使用import命令的时候,用户需要知道a.js所暴露出的变量标识符
使用export default命令,为模块指定默认输出,这样就不需要知道所要加载模块的变量名
//a.js
var sex="boy";
export default sex(sex不能加大括号)
//一个文件内最多只能有一个export default
其实此处相当于为sex变量值"boy"起了一个系统默认的变量名default,自然default只能有一个值
// b.js
本质上,a.js文件的export default输出一个叫做default的变量,然后系统允许你为它取任意名字。所以可以为import的模块起任何变量名,且不需要用大括号包含
import any from "./a.js"
import any12 from "./a.js"
console.log(any,any12) // boy,boy
import和export这两个命令现在在任何浏览器中都是不支持的, 同时babel也无法将其转换为浏览器支持的ES5, 原因在于:
babel只是个翻译,假设a.js 里 import 了 b.js, 对a.js进行转码,只是翻译了a.js,并不会把b.js的内容给读取合并进来, 如果想在最终的某一个js里包含 a.js,b.js 的代码,那就需要用到打包工具
所以我在这里讲解一下如何使用webpack工具将带有import和export语法的JS文件, 通过打包工具生成所有浏览器都支持的单个JS文件