ES6之代码模块化

本文详细介绍了ES6的模块化机制,包括直接和间接使用export导出,使用export...from进行模块成员的导入与导出,以及默认导出的规则。同时,讲解了模块导入的语法,如import * as、import {}


前话

  • 在ES6之前,由于ECMAScript不具备模块化管理能力,往往需要借助第三方类库
  • 例如:遵守AMD规范的 RequireJS 或 遵循CMD规范的SeaJS 才能实现模块加载
  • ES6引入模块化标准,注意,模块中的代码默认运行在严格模式中
  • 一个模块就是一个独立的JS文件

模块化的导出

  • 注意:
    • 1.如果你想要直接在js文件写下面代码,那么你需要在 package.json 文件中这样设置:"type": "module",就可以支持ES module
    • 2.或者你可以将js文件的后缀改为 .mjs

直接使用export关键字导出

  • 注意:命名导出的变量或函数都需要有名称
export let name = 'zsy'
export function getName() {
    return 'zsy'
}
export class People {
    getName() {
        return 'zsy'
    }
}
  • 注意:export导出的是变量本身的引用,比如上述的name变量,如果该name变量在模块内部实时更新了,那么导出的变量的值也会随之改变

间接使用export关键字导出

let name = 'zsy'

function getName() {
    return 'zsy'
}

// export { name, getName }

// 注意:可以使用 as 关键字设置别名
export {
    name as myName, getName as myGetName
}

使用export…from

// export * from './1.js'; // 导出全部

// export { myName } from './1.js'; // 导出部分

export { myName as myName2 } from './1.js' // 导出部分并设置别名
export { myName } from './1.js'; // 导出部分

// 上面的代码相当于下面这样:
import { myName } from './1.js'

export { myName } 

默认导出

  • 注意:一个模块只能存在一个默认导出
// import name from './2.js'  // 写法一

// import name,{age} from './2.js'  // 写法二:注意,默认导入一定要放在前面

// import name,* as people from './2.js'  // 写法三

// import {default as myName} from './2.js'  // 写法四

模块化的导入

导入的写法

import * as people from './1.js'  // 导入全部
import { name } from './1.js'   // 导入部分
import {name as myName } from './1.js'  // 导入部分并设置别名
  • import语句在内部实现了单例模式,尽管上面的代码对同一模块执行了3次导入,但该模块只会被实例化一次

更新导入的变量的值

  • 用import语句导入的变量都是只读的
  • 下面代码演示间接的更新导入的变量的值
export let name = 'zsy'
export function setName(str) {
    name = str
}
  • 然后在另一个模块中
import {name, setName} from './1.js'
console.log(name)  // zsy

setName('peiqi')
console.log(name) // peiqi

导入的成员变量默认会被提升

  • 从模块中导入的成员默认都被提升至当前模块作用域的顶部,类似于声明提升
console.log(name); // zsy
console.log(getName())  // peiqi

import { name, getName } from './1.js'

仅使用import实现脚本预加载

import './jquery.js'
  • 这些脚本可以是自己封装的代码段
  • 也可以是jQuery,Zepto等第三方库

默认导出

  • 注意:一个模块只能存在一个默认导出
let name = 'zsy'
export default name;  // 写法一

// export default function getName(){
//     return 'zsy1'
// }  // 写法二

// export default function(){
//     return 'zsy2'
// }  // 写法三

// export {name as default}  // 写法四
// let name;
// export default name = 'zsy'  // 写法正确

// export default 'zsy' // 写法正确

// export default let name = "peiqi"  // 写法错误

模块化的限制

  • 由于ES6中的模块被设计成了静态的,因此需要在编译阶段就明确模块之间的依赖关系
  • 而不是在运行过程中动态计算

模块路径不能设为变量或表达式

  • 下面的写法都是错误的
// let myPath = './1.js'

// export * from myPath; // 变量

// export * from './' + '1.js';  // 表达式

// import * as people from myPath;  // 变量

// import * as people form './' + '1.js';  // 表达式 

模块化无法动态的导入和导出

  • export 和 import语句都是静态的,无法动态导出和导入
  • 并且只能出现在模块的顶层作用域中,不能出现在块级或函数作用域中
  • 下面的代码是错误的
// 函数作用域
function getName() {
    export * from './1.js';
    import * as people from './1.js'
}

// 块级作用域
if (true) {
    export * from './1.js';
    import * as people from './1.js'
}

用 script 标签加载模块

  • 在浏览器中嵌入模块文件,需要将它的type属性设为’module’
  • 在加载模块时为了避免脚本阻塞,会自动应用布尔属性defer,即HTML文档的解析和模块文件的下载是同时进行的,待到解析完后才会执行模块
<script src="1.js" type="module"></script>

<script type="module">
    import name from './1.js'
    console.log(name)
</script>
<script src="./2.js" type="module"></script>
  • 上面的代码会依次执行,先执行第一个外部模块,再执行第二个内联模块,最后执行第三个外部模块
  • 注意:每个模块只会被加载一次
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值