Module(import/require/export)的学习笔记-ES6系列4

module的学习参考了以下大大们的博客~仅为自己的学习笔记。
http://es6.ruanyifeng.com/#docs/module

1. 模块化的需求

为什么要使用模块化,前端模块化的发展历程,在我的上一篇学习笔记《前端模块化的学习笔记》中有写
https://blog.csdn.net/hongtaochi0464/article/details/92572860

在学习这一章的时候,应当将ES6标准的模块化与CommonJS规范的模块化进行区分。下面先学习一下ES6模块化的语法~

2. ES6模块化的语法

在ES6中,我们使用export导出接口,使用import引入模块。

2.1 export

在模块化中,我们希望一个模块是独立的文件,外部不能随意访问和获取我们定义的变量。只能通过我们给出的接口来进行操作。ES6模块中,使用export来导出接口,具体的写法如下:

//module1.js
export var userName = "cjx"
export var age = "18"
export function speak(){
	console.log(userName+"is speaking");
}

也可以export一个对象(使用{}进行export),如:

//module1.js
var userName = "cjx"
var age = "18"
function speak(){
	console.log(userName+"is speaking");
}
export { userName, age, speak }

一般情况下,export输出的变量就是本来的名字。可以使用as关键字重命名。

//module1.js
var userName = "cjx"
var age = "18"
function speak(){
	console.log(userName+"is speaking");
}
export { userName as name, age, speak }

export命令必须处于模块顶层,不能处于块级作用域内。

2.2 import

在ES6中,使用import命令来加载其他模块export出来的对外接口。
如我们想要在main.js中引入上面module.js暴露出来的接口,就可以用下面的写法

//main.js
import { userName, age, speak } from "./module.js";
speak();
console.log("我叫"+userName+",今年"+age+"岁")

import 也可以使用as关键字来对引入的变量进行重命名,写成如下:

//main.js
import {userName as name} from "./module.js"

2.3 *

除了指定加载某个(些)接口,还可以使用*指定一个对象,将所有的接口都加载在这个对象上。如下面的例子:

//module1.js
var userName = "cjx"
var age = "18"
function speak(){
	console.log(userName+"is speaking");
}
export { userName, age, speak }

现在我们使用*来加载这个模块

//main.js
import * as m1 from "./module.js"

m1.speak();
console.log("我叫"+m1.userName+",今年"+m1.age+"岁")

2.4 export default

使用export default,可以为模块指定默认输出。用其他模块加载该模块时,import命令可以为该接口指定任意名字。如以下写法:

//module.js
export var userName = "cjx"
export var age = "18"
export default function speak(){ 
	console.log(userName+"is speaking");
}

(export default命令也可用在非匿名函数之前,加载的时候会视同匿名函数来加载)

//main.js
import f1 from "./module.js"
f1()

本质上,export default就是输出一个叫做default的变量或方法,然后系统允许你为它取任意名字。因此,一个模块只能有一个默认输出。export default命令在一个模块中只能使用一次。且import命令后面不用加大括号就能唯一获取到default命令。

ES6模块中还支持同时import默认方法和其他接口,如:

//main.js
import f1, {userName,age} from "./module.js"

3. commonJS模块化的语法

在commonJS中,我们使用module.exports导出接口,使用require来引入模块。

3.1 module.exports

将上面的module.js用commonJS模块化的语法写成如下

//module.js
module.exports = {
	userName : "cjx",
	age : "18",
	speak : function(){
		console.log(this.userName+" is speaking");
	}

}

3.2 require

将上面的main.js用commonJS模块化的语法写成如下:

//main.js
var o1 = require("./module.js")
o1.speak();
console.log(o1)

我们使用node来执行一下main.js,输出结果如下:
在这里插入图片描述

4. 比较ES6模块化和commonJS模块化

(1)ES6模块的加载是“编译时加载”,commonJS模块的加载是"运行时加载"。
对于commonJS模块来说

let { userName, age, speak } = require("./module.js")

等同于

let m1 = require("./module.js")
let userName = m1.userName
let age = m1.age
let speak = m1.speak

即相当于 加载了整个module模块再去从加载出的对象中分别读取方法
而对于ES6模块来说

let { userName, age, speak } from "./module.js"

就是单纯的从module模块中加载三个方法,其他方法是不加载的。
(2)import命令具有提升效果,会提升到整个模块的头部执行。如以下的代码不会报错:

speak();
console.log("我叫"+userName+",今年"+age+"岁")
import { userName, age, speak } from "./module.js";

(3)require可以实现条件加载

// import报错
if (x === 2) {
  import module from "./module.js"
}
//require可运行
if (x === 2) {
  var module = require("./module.js")
}

[注]目前已有提案使用import()来进行条件加载。import()返回一个Promise对象。更多的可看阮一峰的博客~
(4)export语句输出的接口,与其对应的值是动态绑定关系,即通过该接口,可以取到模块内部实时的值。

//module.js
export let age = 18;
export oneYearAfter(){
	age++;
}
//main.js
import {age,oneYearAfter} from "./module.js"
console.log(age); //18
oneYearAfter();
console.log(age); //19

CommonJS 模块输出的是值的拷贝,也就是说,一旦输出一个值,模块内部的变化就影响不到这个值。

//module.js
module.exports = {
	age : 18,
	oneYearAfter : function(){
		this.age++
	}
}
let {age,oneYearAfter} = require("./module.js") 
console.log("age1:"+age);
oneYearAfter();
console.log("age2:"+age);

我们使用node运行这个main.js,结果如下:

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值