下面要写出的ES Module的语法,现在还无法在node直接执行,建议使用babel转码后执行(webpack配置babel执行ES module语法)
首先,在谈及ES module的语法前,要先明确一点,ES module默认使用严格模式
javascript严格模式整理,所以松散模式下的一些不会报错的地方在使用ES module时要注意
export
输出方式
1. 将整个声明输出
简单的变量
export var a = 1;
方法
export function fn(){
// ...
}
类
export class c{
// ...
}
2. 放在花括号内输出
var a = 1;
var b = 2;
export { a , b };
function fn(){
// ...
}
export { fn };
class c{
// ...
}
export { c };
3. as语法
ES module可以给输出的内容重命名,使用as来实现
var a = 1;
export { a as b };
注意点
命令所在
export命令可以写在当前模块顶层作用域的任何地方,写在块级作用域中会报错
if (true) {
export var b = 2;
}
动态性
export命令输出的值是动态性的,在当前文件变量修改时,export输出的值也会随之变化
export var a = 1;
setTimeout(() => a = 2, 500);
上面这段代码,在500ms后输出的a的值会改变
import
输入方式
1. 花括号引入
import {…} from …
import { a } from 'xxx.js'
console.log(a);
花括号内的内容是其他模块export输出的内容,用as语法时是写 as 后的名称
from后面的路径可以是绝对路径,相对路径,或者是模块名
2. as语法
将引入的内容使用另一种别名,即等同于赋值给另一个变量
import { a as b } from 'xxx.js'
3. 导入整个模块
import ‘module’
注意点
sington
import命令是sington即单例模式的,多次引用只会被当作引用一次
(单例模式只在第一次引用时引用,后面的引用会直接使用之前引用的内容:JavaScript设计模式笔记(一)单例模式))
import { a } from 'xxx.js'
import { a } from 'xxx.js'
这里写了两句import语句,实际上只import了一次
import { a } from 'module.js'
import { b } from 'module.js'
// 等同于
import { a , b } from 'module.js'
上面代码中的这两种情况,在执行上是完全相同的,因为是引入同一个模块中的两个相同的变量
只读性
import命令引入的变量都是只读的,不能对其重新赋值,如果对import的变量进行赋值,则会报Syntax Error的错误
import { a } from 'xxx.js'
a = 2; // Syntax Error : 'a' is read-only
提升性
和var的变量声明提升一样,import引入的变量也会提升到整个模块的头部,被首先执行
console.log(a);
import { a } from 'xxx.js'
这里的a可以正常输出
静态执行
import是静态执行的,和require不一样,import是在编译的时候执行的,所以不能使用表达式和变量,也不能在块级作用域中使用
下面的代码都是错的
import { 'a'+'b' } from 'xxx.js'
let a = 'b';
import { a } from 'xxx.js'
if(true){
import { b } from 'xxx.js'
}
这里的代码分别使用了拼接字符串,使用变量的值以及if-else语句,这些是在运行阶段执行的内容,在编译阶段不会执行这些内容,所以会报错
export default
输出语法
1. 声明后输出变量
var a = 1;
export default a;
2. 输出匿名函数
export default function(){
// ...
}
// 输出非匿名函数也会被当作匿名函数
// 下面的输出对于import来说和上面的一样
export default function fn(){
// ...
}
3. 放在花括号中输出
var a = 1;
var b = 2;
export default { a , b }
与export的不同
不能输出声明
使用export命令时,我们可以直接输出声明,但是使用export default时,不能输出声明
// 正确写法
export var a = 1;
var a = 1;
export default a;
// 错误写法
export default var a = 1;
import时能否修改变量名
直接使用export命令来输出内容,在import时必须知道export时输出的变量名或者函数名,类名,而使用export default时,在import的时候可以忽略输出时的变量名
// module.js
var a = 1
export { a }
// main.js
import { a } from './module.js'
// module.js
var a = 1
export default a
// main.js
import b from './module.js'
上面两段代码可以看出,使用export命令输出变量a,import的时候必须使用变量名a,而使用export default时不用使用同样的变量名,所以上面第二段代码import的时候可以使用b做为变量名
唯一性
export default只能使用一次,如同其名default默认,只能有一个默认的,而export是能够多次输出的
实质
export default实际上是将命令后面的内容赋值给一个变量default然后输出,所以可以通过使用export的as输出来达到同样的效果
export { a as default}
// 等同于
export default a
也正因为这样,所以我们不能在export default后面使用声明语句,因为我们不能将一个声明语句赋值给一个变量
在浏览器中的使用
现在在浏览器中,已经可以使用ES module的语法了
我们可以将script标签的type属性设置为module来使用ES module的语法,下面写个例子
根目录创建index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script type="module">
import {a} from "./index.js"
console.log("a",a)
</script>
</body>
</html>
同样在根目录,创建一个index.js
export const a = 1
此时双击打开html文件,可能会报这样的错误
将这个错误翻译一下
加载模块脚本失败:服务器以非javascript MIME类型""响应。根据HTML规范,对模块脚本执行严格的MIME类型检查。
实际上,这是因为我们是在本地文件直接打开的,我们只要将它放在一个服务器下启动就可以了,使用vscode的话可以直接使用插件live server启动
启动后可以看到
控制台打印除了从index.js引用的a变量,然后我们再测试其动态性
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script type="module">
import {a} from "./index.js"
setInterval(()=>{ console.log("a",a) },1000)
</script>
</body>
</html>
index.js
export var a = 1
setInterval(() => {
a++
}, 1000)
启动服务器打开页面,可以看到
动态性被成功验证
参考自阮一峰的《ECMAScript6入门》
ES6学习笔记(一)let和const
ES6学习笔记(二)参数的默认值和rest参数
ES6学习笔记(三)箭头函数简化数组函数的使用
ES6学习笔记(四)解构赋值
ES6学习笔记(五)Set结构和Map结构
ES6学习笔记(六)Iterator接口
ES6学习笔记(七)数组的扩展
ES6学习笔记(八)字符串的扩展
ES6学习笔记(九)数值的扩展
ES6学习笔记(十)对象的扩展
ES6学习笔记(十一)Symbol
ES6学习笔记(十二)Proxy代理
ES6学习笔记(十三)Reflect对象
ES6学习笔记(十四)Promise对象
ES6学习笔记(十五)Generator函数
ES6学习笔记(十六)asnyc函数
ES6学习笔记(十七)类class
ES6学习笔记(十八)尾调用优化
ES6学习笔记(十九)正则的扩展
ES6学习笔记(二十)ES Module的语法