ES6模块

本文深入探讨了JavaScript模块化的必要性,从立即执行函数的模拟模块到ES6的模块系统。ES6的模块解决了全局变量污染和加载顺序管理的问题,提供了export和import关键字进行模块的导入导出。exportdefault用于单一默认导出,而export则支持多种导出方式。此外,还介绍了模块中的this指向、import()函数的动态导入以及模块的复合写法。通过理解这些概念,开发者能更好地组织和管理代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、为什么需要模块

起初,项目的代码量不大时,常把所有代码写在一个文件中。随着代码量的不断增加,这样做会带来两个问题:一、不利于分工合作;二、不利于后期维护。因此,需要依据代码功能把代码从一个文件拆分到不同的文件。但是,现在又产生一个新的问题,多个文件的变量都位于全局作用域中,很容易产生冲突,为了解决这个问题,就有了模块。

最初,ES标准中还没有模块和模块系统的支持,只能通过立即执行函数来模拟模块的功能。具体做法是:把不同文件中的代码都放在立即执行函数中,然后把可能会被其他代码使用的变量、函数、类通过全局对象的属性暴露出去。如下代码所示:

(function() {
	class Person {
		constructor(name, age) {
		this.name = name;
		this.age = age;
		}
	}

	window.Person = Person;
})();

通过立即执行函数模拟的模块,大大减少了全局变量,但是依然存在不少通过全局对象属性暴露的变量,例如,window.Person = Person;,更大的问题是,我们需要手动管理加载文件的顺序,例如,文件A中的类继承了文件B中的类,那么在HTML文件中,<script src="A.js"></script> 必须先于<script src="B.js"></script> 引入,如果存在大量的复杂的依赖关系,手动管理依赖是非常困难的。这是立即执行函数模拟(实现)模块存在的两个主要问题。

下文中介绍的ES6中引入的模块和模块系统,会解决立即执行函数模拟模块存在的问题~~

二、 模块和模块系统

1、 模块
模块是局部作用域代码块

在ES6中一个模块本质是一个文件

2、模块系统

模块系统主要解决问题:

  • 模块化
  • 消除全局变量
  • 管理加载顺序

以前,ES还没有提供模块的原生支持时,第三方JS库,例如,RequireJS、SeaJS等实现模块系统的功能。

在HTML代码中引入一个模块的方式

<script src="file.js" type="module"></script>

比起一般的引入方式,多了一个type属性,属性值module表示以模块的方式引入文件。如果不添加属性"type="module,那么,文件以普通的方式引入,文件中的变量会作为全局变量处理。

什么时候或场景需要把文件以模块方式引入呢?
当文件中出现import或export关键字时。

三、模块的两种导入和导出

一个模块没有导出,也可以导入。只是将模块中的代码执行一遍,没有暴露任何变量

1、export default 导出和对应的import导入

export default 表达式; 

表达式:基本类型的字面量,变量,函数和类的表达式。函数和类表达式可以匿名。

export default 1;
export default function(){};
export default class{}
const str = 'hello';
export default str;

一个模块只能定义一个exprot default,不能导出多个。

export default 1;
export default 'hello';

会出现报错:

在这里插入图片描述

2、exprot导出和对应的improt导入语法

基本语法

方式一:export 声明语句;
export let/const/var variable = value;
export function foo(){}
exprot class Clz{}
方式二:先声明后export{变量名}
let variable = value;
exprot {variable};

注意 普通变量、函数和类表达式不能匿名。不能是基本类型值。

import {variable} from XXX.js

导出导入多个

利用基本语法方式二

const variable = value;
function  foo() {}
class Clz {}

// 导出多个
export {variable, foo, Clz};

导出导入起别名

export {variable as username}

导入的”角色“的名字和我当前代码冲突,就可以别名

import {Clz as Person}

整体导入
包括export default导出的角色

import * as obj from 'module.js';

同时导入

import {variable, foo, Clz} from ‘module.js’
import def from ‘module.js’

export和exprot default可以同时导出,不过export default必须在最前面先导出,
import def, {variable, foo, Clz } from ‘module.js’

也可以分开导入
import def from ‘module.js’
import {variable, foo, Clz } from ‘module.js’

想法
export 对标Java中的public
没有export 对标Java中的private

四、其他注意事项

1、模块本身作用域中的this指向undefined

应用,可以在文件首部添加以下代码,来提示用户应该以为模块的方式应用文件

if (typeof this !== 'undefined') {
    throw new Error('请以模块方式引入该文件');
}

2、 import关键字和import()函数

import和export 命令会先于其他代码执行,和它所在的位置无关。因此,我们应该把它们放在模块的首部,而不是代码块,例如if代码块中。

import() 可以实现条件导入,即满足某些条件,例如,是否是PC端、移动端,而导入不同的模块。

此函数不是标准,只是提案。可以配合webpack解决兼容性问题。

3、 导入导出的复合写法

在这里插入图片描述

五、 总结

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
表达式包括基本类型值字面量或变量,函数、类表达式,可以匿名

在这里插入图片描述
声明即变量的声明;语句即表达式,包括变量,函数或者类的声明。

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

明月几时有666

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值