前置知识
1、commonjs规范:
- 一个文件就是一个模块
- 每个模块都有单独的作用域
- 通过module.exports导出成员
- 通过require函数载入模块
commonjs以同步方式加载模块。node是启动时加载模块,执行过程中不需要加载;同步方式不适应浏览器,由此出现了require()模块,在浏览器中以异步方式加载模块。
模块化标准规范最佳实践: node.js遵循commonjs规范,浏览器环境遵循ES Module(主流前端模块化规范)规范
2、ES Module特性
- 自动采用严格模式,忽略'use strict'
- 每个ESM模块都是单独的私有作用域
- ESM是通过CORS去请求外部js模块的
- ESM的script标签会延迟执行脚本
<body>
<!-- 通过script添加Type = module 的属性,就可以在ES Module的标准执行其中的js代码 -->
<script type="module">
console.log("this is module");
</script>
<!--1、 ESM 自动采用严格模式 忽略 'use strict' -->
<!--2、每个ES Module都是运行在单独私有作用域中 -->
<script type="module">
var foo = 100
console.log(100);
</script>
<script type="module">
console.log(foo);//报错
</script>
<!-- 3、ESM是通过CORS方式请求外部js模块的 服务端需要支持CORS -->
<!-- 4、ESM 的script标签会延迟执行脚本 -->
<script src="demo.js"></script>
<p>先执行demo.js脚本才会执行这句话</p>
<script src="demo.js" type="module" ></script>
<p>我先出现,加了module使用延期执行,先渲染页面再执行脚本</p>
</body>
3、ES Module导入和导出
1、
export {
hello as default, //设置成了默认导出成员
name as fooName
}
import {default as newHollo} from "./module.js" //导入时必须重命名 default是关键词
2、
export default hello //将该变量当成默认导出
import abc from './module.js' //默认导出下变量名可任意取
3、
//export 后面的{}不是对象字面量 而是固定语法
//export 并不是复制值导出去,而是导出的是一个引用,导出的是name、age、hello所在的内存空间所在的引用关系给了引入的文件
export {
name,hello,age
}
// 使用exprot default 才是对象,后面也可以直接使用变量
export default {name,age}
//import也不是解构而是固定语法 引入的是name和age所在内存空间的引用关系地址 对外暴露的引用关系是只读
import {name,age} from './module.js'
4、
--import引入时使用完整的文件名称,不要去掉.js;
--使用相对路径时使用./开头,不然有可能当成第三方引入;
--也可以使用绝对路径和完整的url
5、只是需要执行模块不需要提取模块中的成员 可以使用以下两种方法
import {} from './module.js'
import './module.js'
6、全部导入
import * as mod from './module.js'
7、动态导入模块(应用场景:需要某些条件满足过后才导入该模块)
import ('./module.js').then(function (res){
//返回的是一个promise 当模块加载完后自动执行then里面的函数。模块对象可以通过参数res拿到
console.log(res)
})
8、同时导出命名成员和默认成员,两种方法如下:
import {name,age,default as newName} from "./module.js"
import newName , {name,age} from "./module.js" //逗号左边是默认成员 名字任取
9、直接导出所导入的成员
把import {name,age} from "./module.js"变成export {name,age} from "./module.js"
//注意点:
export {name,age} from "./module.js"
//当前作用域无法访问这些成员
console.log(name,age);//报错
4、ES Module浏览环境支持及polyfill
//ie不支持es6引入polyfill使其支持es6语法
<script nomodule src="https://unpkg.com/promise-polyfill@8.2.0/dist/polyfill.min.js"></script>
//引用的是babel及时运行在浏览器的环境的一个版本
<script nomodule src="https://unpkg.com/browser-es-module-loader@0.4.1/dist/babel-browser-build.js"></script>
//引入的是ES Module loader的核心代码 读取该代码交给babel转换时代码正常工作
<script nomodule src="https://unpkg.com/browser-es-module-loader@0.4.1/dist/browser-es-module-loader.js"></script>
//注意如果支持ES Module的浏览器 还引入有polyfill ES Module会执行两次 可以使用nomodule属性避免,
//加了该属性,支持的则不会再执行polyfill,也就不会重复执行ES Module
//(也就开发阶段玩玩,生产阶段勿cue;该原理时运行阶段动态解析脚本,效率会有所降低;生产阶段需要预先编译出来才行)
<script type="module">
import { foo } from './module.js'
console.log(foo)
</script>
5、在node环境中运行ES Module
- ES Module中可以导入CommonJS模块
- CommonJS中不能导入ES Module模块
- CommonJS始终只会导出一个默认成员
- 注意import不是解构导出对象
更新中...