ES6 随笔 9-module

1.概述

ES6 模块的设计思想是尽量的静态化,使得编译时就能确定模块的依赖关系,以及输入和输出的变量。

2.export

2.1 使用

//一个一个导出
export var firstName = 'Michael';
export var lastName = 'Jackson';
export var year = 1958;
//写成一条语句
export { firstName, lastName, year };

2.2 能否建立对应关系

不能直接导出常量,常量导出后无法建立对应关系,这与ES6的模块化设计理念是相通的。

// 报错
export 1;

// 报错
var m = 1;
export m;

//正确
var m =  1;
export {m}

2.3 特点

default 限一个 对外相当于变量名default

正是因为export default命令其实只是输出一个叫做default的变量,所以它后面不能跟变量声明语句。

// 正确
export var a = 1;

// 正确
var a = 1;
export default a;

// 错误
export default var a = 1;

3.import

3.1 使用

import from

3.2 特点

可以从ES6的模块化设计理念中发现:
import指令会自动提升,
如果处于块级作用域内,就会报错,没法做静态优化(不需要根据条件语句)

module 加载实现默认启用严格模式this为undefined相同模块只会加载一次

default及其他非default一块儿 xxx(default别名),{},因为{}或*(忽略default)

4.export和import指令合并

5.as

import和export都可以使用as给模块起别名

6.import()

ES2020提案 引入import()函数,支持动态加载模块。
const main = document.querySelector(‘main’);

import(`./section-modules/${someVariable}.js`)
  .then(module => {
    module.loadPageInto(main);
  })
  .catch(err => {
    main.textContent = err.message;
  });

7.模块继承

8.模块加载原理

8.1 html外部脚本加载原理

    //(同缺省)异步加载,等到页面页面渲染完,再加载模块
    //同步加载,模块加载完成,停止渲染并立即执行,执行结束后,再恢复渲染

8.1 Common.js & ES6

CommonsJS输出值拷贝,ES6输出值引用
CommonsJS运行时加载,ES6是编译输出时接口()
CommonsJS的require()是同步加载模块,ES6的import是异步加载,有一个独立的模块依赖的解析阶段
CommonsJS的this指向当前模块,ES6则为undefined

8.2 Common.js 加载原理

CommonJS 模块输出的是值的缓存,不存在动态更新,
目前阶段,通过 Babel 转码,CommonJS 模块的require命令和 ES6 模块的import命令,可以写在同一个模块里面,但是最好不要这样做。因为import在静态解析阶段执行,所以它是一个模块之中最早执行的。

8.8 多文件的常量维护模块

如果想设置跨模块的常量(即跨多个文件),或者说一个值要被多个模块共享,可以采用下面的写法。

// constants.js 模块
export const A = 1;
export const B = 3;
export const C = 4;
// test1.js 模块
import * as constants from './constants';
console.log(constants.A); // 1
console.log(constants.B); // 3
// test2.js 模块
import {A, B} from './constants';console.log(A); // 1
console.log(B); // 3        

9. Node.js模块加载

js模块包括:ES6模块(ESM),CommonsJS模块(CJS)
Node.js v13.2 默认使用ESM
	.mjs文件总是以 ES6 模块加载,.cjs文件总是以 CommonJS 模块加载
	.js文件的加载取决于package.json里面type字段的设置。

Package.json
package.json文件有两个字段可以指定模块的入口文件:main和exports。

9.1 main字段

比较简单的模块,可以只使用main字段,指定模块加载的入口文件。
如果没有type字段,index.js就会被解释为 CommonJS 模块。

// ./node_modules/es-module-package/package.json
{
	"type": "module",
	"main": "./src/index.js"
}

9.2 exports字段

exports字段的优先级高于main字段。它有多种用法。
由于exports字段只有支持 ES6 的 Node.js 才认识,所以可以用来兼容旧版本的 Node.js。

(1)子目录别名
package.json文件的exports字段可以指定脚本或子目录的别名。

// ./node_modules/es-module-package/package.json
{
  "exports": {
    "./submodule": "./src/submodule.js"
  }
}

(2)main 的别名
exports字段的别名如果是.,就代表模块的主入口,优先级高于main字段,并且可以直接简写成exports字段的值。

{
  "exports": {
    ".": "./main.js"
  }
}

// 等同于
{
  "exports": "./main.js"
}

(3)条件加载
利用.这个别名,可以为 ES6 模块和 CommonJS 指定不同的入口。目前,这个功能需要在 Node.js 运行的时候,打开–experimental-conditional-exports标志。

{
  "type": "module",
  "exports": {
    ".": {
      "require": "./main.cjs",
      "default": "./main.js"
    }
  }
}

//等同于
{
  "exports": {
    "require": "./main.cjs",
    "default": "./main.js"
  }
}

9.3 使用ES6加载CommonJS模块(或反过来)

ES6 模块通过module.createRequire()方法可以加载 CommonJS 模块。但是,这种写法等于将 ES6 和 CommonJS 混在一起了,所以不建议使用。

9.4 同时支持两种格式的模块

一个模块同时要支持 CommonJS 和 ES6 两种格式,也很容易。
如果原始模块是 ES6 格式,那么需要给出一个整体输出接口,比如export default obj,使得 CommonJS 可以用import()进行加载。
如果原始模块是 CommonJS 格式,那么可以加一个包装层。
另一种做法是在package.json文件的exports字段,指明两种格式模块各自的加载入口。

9.5 Node.js 的内置模块可以整体加载,也可以加载指定的输出项。

9.6 加载路径

ES6 模块的加载路径必须给出脚本的完整路径,不能省略脚本的后缀名。
为了与浏览器的import加载规则相同,Node.js 的.mjs文件支持 URL 路径。

目前,Node.js 的import命令只支持加载本地模块(file:协议)和data:协议,不支持加载远程模块。另外,脚本路径只支持相对路径,不支持绝对路径(即以/或//开头的路径)。

9.7 内部变量

ES6 模块应该是通用的,同一个模块不用修改,就可以用在浏览器环境和服务器环境。为了达到这个目标,Node.js 规定 ES6 模块之中不能使用 CommonJS 模块的特有的一些内部变量(诸如:this、arguments、require)。

9.8 循环加载

“循环加载”(circular dependency)指的是,a脚本的执行依赖b脚本,而b脚本的执行又依赖a脚本。

通常,“循环加载”表示存在强耦合,如果处理不好,还可能导致递归加载,使得程序无法执行,因此应该避免出现。

9.9 CommonJS 模块加载原理(加载时执行)

CommonJS 的一个模块,就是一个脚本文件。require命令第一次加载该脚本,就会执行整个脚本,然后在内存生成一个对象。

以后需要用到这个模块的时候,就会到exports属性上面取值。即使再次执行require命令,也不会再次执行该模块,而是到缓存之中取值。也就是说,CommonJS 模块无论加载多少次,都只会在第一次加载时运行一次,以后再加载,就返回第一次运行的结果,除非手动清除系统缓存。

由于 CommonJS 模块遇到循环加载时,返回的是当前已经执行的部分的值,而不是代码全部执行后的值

你可能感兴趣的:(Dhtml)