深入理解ES6笔记(十三)用模块封装代码

发布时间:2019-08-11 发布网站:脚本宝典
脚本宝典收集整理的这篇文章主要介绍了深入理解ES6笔记(十三)用模块封装代码脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。
主要知识点:什么是模块、模块中的导出、模块中的导入
图片描述

《深入理解ES6》笔记 目录

模块的定义

模块( Modules )是使用不同方式加载的 JS 文件(与 JS 原先的脚本加载方式相对)。这种不同模式很有必要,因为它与脚本( script )有大大不同的语义:

  1. 模块代码自动运行在严格模式下,并且没有任何办法跳出严格模式;
  2. 在模块的顶级作用域创建的变量,不会被自动添加到共享的全局作用域,它们只会在模块顶级作用域的内部存在;
  3. 模块顶级作用域的 this 值为 undefined ;
  4. 模块不允许在代码中使用 HTML 风格的注释(这是 JS 来自于早期浏览器的历史遗留特性);
  5. 对于需要让模块外部代码访问的内容,模块必须导出它们;
  6. 允许模块从其他模块导入绑定。

模块的导出

可以使用 export 关键字将已发布代码部分公开给其他模块。最简单方法就是将 export放置在任意变量、函数或类声明之前,从模块中将它们公开出去:

// 导出数据
export VAR color = "red";
export let name = "Nicholas";
export const magicNumber = 7;
// 导出函数
export function sum(num1, num2) {
    return num1 + num2;
}
// 导出类
export class Rectangle {
    constructor(length, width) {
        this.length = length;
        this.width = width;
    }
}
// 此函数为模块私有
function suBTract(num1, num2) {
    return num1 - num2;
}
// 定义一个函数……
function multiply(num1, num2) {
    return num1 * num2;
}
// ……稍后将其导出
export {
    multiply
};

注意:

  • 除了 export 关键字之外,每个声明都与正常形式完全一样。
  • 每个被导出的函数或类都有名称,这是因为导出的函数声明与类声明必须要有名称。你不能使用这种语法来导出匿名函数或匿名类,除非使用了 default 关键字

模块的导入

一旦你有了包含导出的模块,就能在其他模块内使用 import 关键字来访问已被导出的功能。 import 语句有两个部分,一是需要导入的标识符,二是需导入的标识符的来模块。
此处是导入语句的基本形式:

import { identifier1, identifier2 } From "./example.js";

导入单个绑定

/ 单个导入
import { sum } from "./example.js";
console.LOG(sum(1, 2)); // 3
//不允许对已导入的绑定重新赋值,于是就会导致错误
sum = 1; // 出错

导入多个绑定

// 多个导入
import { sum, multiply, magicNumber } from "./example.js";
console.log(sum(1, magicNumber)); // 8
console.log(multiply(1, 2)); // 2

导入整个模块

还有一种特殊情况,即允许你将整个模块当作单一对象进行导入,该模块的所有导出都会作为对象的属性存在。例如:

// 完全导入
import * as example from "./example.js";
console.log(example.sum(1,
            example.magicNumber)); // 8
console.log(example.multiply(1, 2)); // 2

导入绑定的一个微妙怪异点

ES6 的 import 语句为变量、函数与类创建了只读绑定,而不像普通变量那样简单引用了原始绑定。尽管导入绑定的模块无法修改绑定的值,但负责导出的模块却能做到一点。例如,假设你想要使用以下模块:

export var name = "Nicholas";
export function setName(newName) {
    name = newName;
}

当你导入了这两个绑定后, setName() 函数还可以改变 name 的值:

import { name, setName } from "./example.js";
console.log(name); // "Nicholas"
setName("Greg");
console.log(name); // "Greg"
name = "Nicholas"; // error

导入导出时重命名

  • 导出时重命名:
function sum(num1, num2) {
    return num1 + num2;
}
//将本地名称sum重命名为add
export { sum as add };
  • 导入时重命名:
//将导入名称重命名为sum
import { add as sum } from "./example.js";
console.log(tyPEof add); // "undefined"
console.log(sum(1, 2)); // 3

模块的默认值

模块的默认值( default value ) 是使用 default 关键字所指定的单个变量、函数或类,而你在每个模块中只能设置一个默认导出,将 default 关键字用于多个导出会是语法错误。

@H_378_406@导出默认值
  • 不使用标识符
export default function(num1, num2) {
    return num1 + num2;
}
  • 使用标识符
function sum(num1, num2) {
    return num1 + num2;
}
export default sum;
  • 使用重命名语法
function sum(num1, num2) {
    return num1 + num2;
}
export { sum as default };
  • 既导出了默认值,又导出非默认值
export let color = 'red';
export default function(num1,num2){
    return num1+num2;
}

导入默认值

  • 只导入默认值
import sum from './example.js';
console.log(sum(1,2));

这个导入语句从 example.js 模块导入了其默认值。注意此处并未使用花括号,与之前在非默认的导入中看到的不同。本地名称 sum 被用于代表目标模块所默认导出的函数。

  • 既导入默认值,又导入非默认值
import sum, { color } from './example.js';
console.log(sum(1,2));
console.log(color);

逗号将默认的本地名称与非默认的名称分隔开,后者仍旧被花括号所包裹。要记住在 import语句中默认名称必须位于非默认名称之前。

  • 对导入默认值重命名
// 等价于上个例子
import { default as sum, color } from "example";
console.log(sum(1, 2)); // 3
console.log(color); // "red"

对已导入的内容再导出

如果在当前模块中对已导入的内容在导出,使用本章已描述过的模式来将已导入的值再导出,就像这样:

import { sum } from "./example.js";
export { sum }

此方法能奏效,但还可以使用单个语句来完成相同任务

export { sum } from "./example.js";

这种形式的 export 会进入指定模块查看 sum 的定义,随后将其导出。当然,你也可以选择将一个值用不同名称导出:

export { sum as add } from "./example.js";

若你想将来自另一个模块的所有值完全导出,可以使用星号( * )模式:

export * from "./example.js";

无绑定导入

有些模块也许没有进行任何导出,相反只是修改全局作用域的对象。尽管这种模块的顶级变量、函数或类最终并不会自动被加入全局作用域,但这并不意味着该模块无法访问全局作用域。诸如 ArrayObject 之类的内置对象的共享定义在模块内部是可访问的,并且对于这些对象的修改会反映到其他模块中。
例如,若你想为所有数组添加一个 pushAll() 方法,你可以像下面这样定义一个模块:

// 没有导出与导入的模块
Array.PRototype.pushAll = function (ITems) {
    // items 必须是一个数组
    if (!Array.isArray(items)) {
        throw new TypeError("argument must be an array.");
    }
    // 使用内置的 push() 与扩展运算符
    return this.push(...items);
};

这是一个有效的模块,尽管此处没有任何导出与导入。

import "./example.js";
let colors = ["red", "green", "blue"];
let items = [];
items.pushAll(colors);

浏览器加载模块

有用过webpack打包js模块的同学可能有经验,使用webpack打包了多个js文件,然后放到HTML使用script加载时,如果加载顺序不对,就会出现找不到模块的错误。

这是因为模块之间是有依赖关系的,就像你使用jQuery的时候,必须先加载jQuery的代码,才能使用jquery提供的方法。

加载模块的方法,总是先加载模块1,再加载模块2,因为module类型默认使用defer属性。

<script type="module" src="module1.js"></script>
<script type="module" src="module2.js"></script>

脚本宝典总结

以上是脚本宝典为你收集整理的深入理解ES6笔记(十三)用模块封装代码全部内容,希望文章能够帮你解决深入理解ES6笔记(十三)用模块封装代码所遇到的问题。

如果觉得脚本宝典网站内容还不错,欢迎将脚本宝典推荐好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。