腾讯一面:你了解ES6的模块化语法吗?

模块化:将一个整体的文件根据功能和逻辑拆分成几个互相依赖的独立文件(模块)。这样做的好处,就是让代码和逻辑能根据不同模块进行解耦,减少每个模块之间的影响,方便我们在复杂项目中对代码的管理和维护。

概念理解如下图:

在ES6之前,是由社区指定的模块加载方案:

  • CJS(CommonJS) 服务器

  • AMD 浏览器

在ES6的标准中,实现了模块功能

  • ESM(ES module)

ES6模块中主要的两个功能:

  • export:对外导出当前模块的数据

  • import:在当前模块中导入另一个模块的数据

让我们来了解两个命令的具体使用。

export

export指令通常也被称为命名导出,用于导出模块内的函数与变量,我们可以看导出时的不同做法:

//module1.js

export var a = 1;

export var b = 'fun';

export function fun(){}

像上述代码中,使用export命令导出了a、b两个变量及函数fun,ES6将module1.js文件视为一个模块,这种写法等价于:

//module1.js

var a = 1;

var b = 'fun';

function fun(){}

export {a, b, fun}

比较前者,这种写法可以明确分辨整个模块具体暴露了哪些内容。

同时我们可以用as关键字进行暴露内容的重命名(这种做法也被称为别名导出),例如:

//module1.js

var a = 1;

var b = 'fun';

function fun(){}

export {

a as a1,

b as b1,

fun as fun1

}

import

import指令用于导入其他模块的函数与变量,我们可以看下基本用法:

//main.js

import { a } from "./module1.js";

console.log(a) // 1

像上述代码中,引入了module1.js文件中暴露的a变量,括号内的变量名必须与module1.js模块中导出的变量名相同。

同时,引入的变量是只读的,不可修改。

//main.js

import { a } from "./module1.js";

a = 2 // Uncaught TypeError: Assignment to constant variable.

如果引入在module1.js中未暴露过对应变量,或者变量名不相同,则会报错:

//main.js

import { a1 } from "./module1.js";

//Uncaught SyntaxError: The requested module './module1.js' does not provide an export named 'b'

既然如此,如果有对应的场景,需要将引入的变量进行重命名(别名导入),import也可以通过as关键字达到目的:

//main.js

import { a as a1 } from "./module1.js";

console.log(a1) // 1

上述代码中,将引入的a变量重命名为a1。

还有更具体的场景,例如导入两个模块,并且这两个模块都导出了同一个命名的变量,那重命名就派上用场:

//main.js

import { a as a1 } from "./module1.js";

import { a as a2 } from "./module2.js";

虽然as解决了同名的场景,但如果导入的两个模块,有大量变量同名,那命名的工作量就变大了:

//main.js

import {

a as a1,

b as b1,

fun as fun1

} from "./module1.js";

import {

a as a2,

b as b2,

fun as fun2

} from "./module2.js";

这种情景,会让导入变量的过程格外麻烦(尤其是命名)。

那我们可以使用*将目标模块中导出的所有变量存放在一个对象上,模块的整体导入(命名空间导入),极大地简化上述情景中的导入过程:

//main.js

import * as module1 from './module1.js'

import * as module2 from './module2.js'

console.log(module1.a)

console.log(module2.a)

注意,上述代码中的module1对象不可扩展,且已有的属性是只读的,不可修改:

//main.js

import * as module1 from './module1.js'

module1.xxx = 2 // TypeError: Cannot add property b, object is not extensible

module1.a = 2 // TypeError: Cannot assign to read only property 'a' of object '[object Module]'

export default

export default(默认导出)的特点如下:

1.导出时不需要命名,一个模块内只能默认导出一次。

2.导入时需要命名,且不用大括号。

我们来看下基本用法:

//exportModule.js

export default function(){

console.log(1)

}

//main.js

import fn form './exportModule.js'

fn() //1

像上述代码,导入时可以随意命名。

但在导出时模块只能有一个默认导出,否则会报错:

//exportModule.js

export default function(){

console.log(1)

}

export default function(){

console.log(2)

}

//Duplicate export of 'default'

Duplicate export of 'default(‘default’被重复导出)

通过这个报错语句我们可以推测下默认导出的本质:”将目标值赋值给default变量“,具体我们看下面这段代码:

//exportModule.js

export default function(){

console.log(1)

}

//main.js

import * as exportModule from './exportModule.js'

console.log(exportModule) // { default: [Function: default] }

exportModule对象中只有一个属性default,存放的就是exportModule模块中默认导出的函数。

同时要避免一些错误的写法,例如:

//错误写法

export default var a = 1

export 1

//正确写法

var a = 1

export default a

//等价于

export default 1

既然了解默认导出的本质,那应该明白错误写法的问题,我们无法将一句声明变量的语句赋值给default变量。

而且,命名导出和默认导出时可以同时使用:

//module.js

export var a = 1

export default function fn(){

console.log(1)

}

//main.js

import * as module from './module.js'

module.default() //1

console.log(module.a) //1

//等价于

import fn,{a} as module from './module.js'

fn() // 1

console.log(a) //1

总结

模块化对大型项目十分重要,利于代码的维护和优化。掌握ES6的模块化语法,对应不同场景进行准确使用,类似文本提及的‘不同模块过多相同命名变量的冲突’需要懂得使用空间命名导入,否则即使有模块化概念,仍然会写出多余而冗长的代码。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
当然可以!ES5(ECMAScript 5)和ES6(ECMAScript 2015)是JavaScript的两个主要版本。以下是它们之间的一些区别: 1. 语法ES6引入了许多新的语法特性,如箭头函数、解构赋值、扩展运算符等,使代码更简洁易读。 2. 块级作用域:ES5中变量作用域只有全局作用域和函数作用域,而ES6引入了块级作用域,使用let和const关键字声明的变量只在块级作用域内有效。 3. 箭头函数:ES6引入了箭头函数,它提供了更简洁的函数定义语法,并且自动绑定了上下文,避免了this指向的问题。 4. 模板字符串:ES6引入了模板字符串,可以使用反引号(`)来定义多行字符串,并且可以插入变量或表达式。 5. 类和模块:ES6引入了class关键字,可以使用面向对象的语法定义类和实例化对象。此外,ES6还引入了模块化的概念,通过export和import关键字可以方便地导出和导入模块。 6. 简化的迭代器和生成器:ES6引入了for...of循环,可以更方便地遍历可迭代对象。此外,ES6还引入了生成器函数,可以通过yield关键字实现暂停和恢复执行。 7. Promise对象:ES6引入了Promise对象,用于更好地处理异步操作,避免了回调地狱的问题。 这只是ES5和ES6之间的一些主要区别,ES6还引入了许多其他特性和改进。然而,需要注意的是,并非所有浏览器都完全支持ES6,所以在开发中需要使用转译工具(如Babel)将ES6代码转换为ES5以确保兼容性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值