首页 > 其他 > 详细

【ES6】Moudle

时间:2019-12-30 01:19:13      阅读:112      评论:0      收藏:0      [点我收藏+]

概述

ES6之前,JS没有模块系统,无法将一个大程序拆分为互相依赖的小文件

社区制定了一些模块加载方案最主要的是CommonJS和AMD,前者用于服务器,后者用于浏览器。

// CommonJS模块,运行时加载
let { stat, exists, readFile } = require(‘fs‘);

ES6模块的设计思想是尽量静态化,使得编译时就能确定模块的依赖关系,以及输入和输出的变量。而上述两者方案只有在运行时才能确定。

// ES6模块,编译时已确定,效率更好
import { stat, exists, readFile } from ‘fs‘;

当然,这也导致了没法引用 ES6 模块本身,因为它不是对象 

ES6模块采用严格模式

严格模式主要有以下限制。

  • 变量必须声明后再使用
  • 函数的参数不能有同名属性,否则报错
  • 不能使用with语句
  • 不能对只读属性赋值,否则报错
  • 不能使用前缀 0 表示八进制数,否则报错
  • 不能删除不可删除的属性,否则报错
  • 不能删除变量delete prop,会报错,只能删除属性delete global[prop]
  • eval不会在它的外层作用域引入变量
  • evalarguments不能被重新赋值
  • arguments不会自动反映函数参数的变化
  • 不能使用arguments.callee
  • 不能使用arguments.caller
  • 禁止this指向全局对象,ES6模块中this指向undefined
  • 不能使用fn.callerfn.arguments获取函数调用的堆栈
  • 增加了保留字(比如protectedstaticinterface

export命令

export命令用于规定模块的对外接口

// profile.js
// 输出变量、函数或类 export let a = ‘lpr‘ export let year = 2020
export function multiply(x, y) { return x * y; }

或者

// profile.js
let a = 111
function v1() { ... }

export { firstName, v1 }

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

function v1() { ... }
function v2() { ... }

export {
  v1 as streamV1,
  v2 as streamV2,
  v2 as streamLatestVersion // 可以用不同的名字输出
}

export命令规定的是对外的接口,必须与模块内部的变量建立一一对应关系

export语句输出的接口,与其对应的值是动态绑定关系,即通过该接口,可以取到模块内部实时的值。

commonJS模块输出的是值得缓存,不存在动态更新

export命令可以出现在模块的任何位置,只要处于模块顶层就可以 

 

import命令

import命令用于输入其他模块提供的功能

import { a,b,c } from ‘./profile.js‘;

如果想为输入的变量重新取一个名字,import命令要使用as关键字,将输入的变量重命名。 

import { lastName as surname } from ‘./profile.js‘;

import命令输入的变量都是只读的,因为它的本质是输入接口。也就是说,不允许在加载模块的脚本里面改写接口

import后面的from指定模块文件的位置,可以是相对路径,也可以是绝对路径,.js后缀可以省略。如果只是模块名,不带有路径,那么必须有配置文件,告诉 JavaScript 引擎该模块的位置。

import命令具有提升效果,会提升到整个模块的头部,首先执行

import是静态执行,所以不能使用表达式和变量

模块的整体加载

import { area, circumference } from ‘./circle‘;
// 整体加载
import * as circle from ‘./circle‘;

export default 命令

使用import命令的时候,用户需要知道所要加载的变量名或函数名,否则无法加载。但是,用户肯定希望快速上手,未必愿意阅读文档,去了解模块有哪些属性和方法。

为了给用户提供方便,让他们不用阅读文档就能加载模块,就要用到export default命令,为模块指定默认输出。

// export-default.js 默认输出一个匿名函数
export default function () {
  console.log(‘foo‘);
}

其他模块加载该模块时,import命令可以为该匿名函数指定任意名字。 

// import-default.js
import customName from ‘./export-default‘;
customName(); // ‘foo‘

比较一下默认输出和正常输出。 

// 第一组
export default function crc32() { // 输出
  // ...
}

import crc32 from ‘crc32‘; // 输入

// 第二组
export function crc32() { // 输出
  // ...
};

import {crc32} from ‘crc32‘; // 输入

export 与 import 的复合写法

export { foo, bar } from ‘my_module‘;

// 可以简单理解为
import { foo, bar } from ‘my_module‘;
export { foo, bar };

但需要注意的是,写成一行以后,foobar实际上并没有被导入当前模块,只是相当于对外转发了这两个接口,导致当前模块不能直接使用foobar。  

模块可以继承

跨模块常量

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

 

// 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

浏览器加载

 传统方法

<script src="path/to/myModule.js" defer></script>
<script src="path/to/myModule.js" async></script>

deferasync的区别是:defer要等到整个页面在内存中正常渲染结束(DOM 结构完全生成,以及其他脚本执行完成),才会执行;async一旦下载完,渲染引擎就会中断渲染,执行这个脚本以后,再继续渲染。一句话,defer是“渲染完再执行”,async是“下载完就执行”。另外,如果有多个defer脚本,会按照它们在页面出现的顺序加载,而多个async脚本是不能保证加载顺

浏览器加载 ES6 模块,也使用<script>标签,但是要加入type="module"属性。

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

异步加载,不会造成堵塞浏览器,即等到整个页面渲染完,再执行模块脚本,等同于打开了<script>标签的defer属性。

ES6 模块与 CommonJS 模块的差异

  • CommonJS 模块输出的是一个值的拷贝,ES6 模块输出的是值的引用。
  • CommonJS 模块是运行时加载,ES6 模块是编译时输出接口。

第二个差异是因为 CommonJS 加载的是一个对象(即module.exports属性),该对象只有在脚本运行完才会生成。而 ES6 模块不是对象,它的对外接口只是一种静态定义,在代码静态解析阶段就会生成

Node.js 加载 

有自己的 CommonJS 模块格式,与 ES6 模块格式是不兼容的。目前的解决方案是,将两者分开,ES6 模块和 CommonJS 采用各自的加载方案。从 v13.2 版本开始,Node.js 已经默认打开了 ES6 模块支持。

Node.js 要求 ES6 模块采用.mjs后缀文件名。也就是说,只要脚本文件里面使用import或者export命令,那么就必须采用.mjs后缀名。Node.js 遇到.mjs文件,就认为它是 ES6 模块,默认启用严格模式,不必在每个模块文件顶部指定"use strict"

如果不希望将后缀名改成.mjs,可以在项目的package.json文件中,指定type字段为module

【ES6】Moudle

原文:https://www.cnblogs.com/Mijiujs/p/12117200.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!