代码编织梦想

ES6 入门教程

ECMAScript 6 入门

作者:阮一峰

本文仅用于学习记录,不存在任何商业用途,如侵删

25 Module 的加载实现

25.2 ES6 模块与 CommonJS 模块的差异

ES6 模块与 CommonJS 模块完全不同。

它们有三个重大差异:

  • CommonJS 模块输出的是一个值的拷贝,ES6 模块输出的是值的引用。
  • CommonJS 模块是运行时加载,ES6 模块是编译时输出接口。
  • CommonJS 模块的require()是同步加载模块,ES6 模块的import命令是异步加载,有一个独立的模块依赖的解析阶段。

第二个差异是因为 CommonJS 加载的是一个对象(即module.exports属性),该对象只有在脚本运行完才会生成。

而 ES6 模块不是对象,它的对外接口只是一种静态定义,在代码静态解析阶段就会生成。

下面重点解释第一个差异。

CommonJS 模块输出的是值的拷贝,也就是说,一旦输出一个值,模块内部的变化就影响不到这个值。请看下面这个模块文件lib.js的例子。

// lib.js
var counter = 3;
function incCounter() {
  counter++;
}
module.exports = {
  counter: counter,
  incCounter: incCounter,
};

上面代码输出内部变量counter和改写这个变量的内部方法incCounter

然后,在main.js里面加载这个模块。

// main.js
var mod = require('./lib');

console.log(mod.counter);  // 3
mod.incCounter();
console.log(mod.counter); // 3

上面代码说明,lib.js模块加载以后,它的内部变化就影响不到输出的mod.counter了。这是因为mod.counter是一个原始类型的值,会被缓存。

除非写成一个函数,才能得到内部变动后的值。

// lib.js
var counter = 3;
function incCounter() {
  counter++;
}
module.exports = {
  get counter() {
    return counter
  },
  incCounter: incCounter,
};

上面代码中,输出的counter属性实际上是一个取值器函数。现在再执行main.js,就可以正确读取内部变量counter的变动了。

$ node main.js
3
4

ES6 模块的运行机制与 CommonJS 不一样。JS 引擎对脚本静态分析的时候,遇到模块加载命令import,就会生成一个只读引用。等到脚本真正执行时,再根据这个只读引用,到被加载的那个模块里面去取值。

换句话说,ES6 的import有点像 Unix 系统的“符号连接”,原始值变了,import加载的值也会跟着变。因此,ES6 模块是动态引用,并且不会缓存值,模块里面的变量绑定其所在的模块。

还是举上面的例子。

// lib.js
export let counter = 3;
export function incCounter() {
  counter++;
}

// main.js
import { counter, incCounter } from './lib';
console.log(counter); // 3
incCounter();
console.log(counter); // 4

上面代码说明,ES6 模块输入的变量counter是活的,完全反应其所在模块lib.js内部的变化。

再举一个出现在export一节中的例子。

// m1.js
export var foo = 'bar';
setTimeout(() => foo = 'baz', 500);

// m2.js
import {foo} from './m1.js';
console.log(foo);
setTimeout(() => console.log(foo), 500);

上面代码中,m1.js的变量foo,在刚加载时等于bar,过了 500 毫秒,又变为等于baz

看看,m2.js能否正确读取这个变化。

$ babel-node m2.js

bar
baz

上面代码表明,ES6 模块不会缓存运行结果,而是动态地去被加载的模块取值,并且变量总是绑定其所在的模块。

由于 ES6 输入的模块变量,只是一个“符号连接”,所以这个变量是只读的,对它进行重新赋值会报错。

// lib.js
export let obj = {};

// main.js
import { obj } from './lib';

obj.prop = 123; // OK
obj = {}; // TypeError

上面代码中,main.jslib.js输入变量obj,可以对obj添加属性,但是重新赋值就会报错。因为变量obj指向的地址是只读的,不能重新赋值,这就好比main.js创造了一个名为objconst变量。

最后,export通过接口,输出的是同一个值。

不同的脚本加载这个接口,得到的都是同样的实例。

// mod.js
function C() {
  this.sum = 0;
  this.add = function () {
    this.sum += 1;
  };
  this.show = function () {
    console.log(this.sum);
  };
}

export let c = new C();

上面的脚本mod.js,输出的是一个C的实例。不同的脚本加载这个模块,得到的都是同一个实例。

// x.js
import {c} from './mod';
c.add();

// y.js
import {c} from './mod';
c.show();

// main.js
import './x';
import './y';

现在执行main.js,输出的是1

$ babel-node main.js
1

这就证明了x.jsy.js加载的都是C的同一个实例。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_44226181/article/details/128010948

es6中module语法与加载实现_这里王工头的博客-爱代码爱编程

欢迎访问我的博客https://qqqww.com/,祝码农同胞们早日走上人生巅峰,迎娶白富美~~~ 文章目录 1 前言2 引入ES6模块的好处2.1 静态加载带来的好处 3 ES6中

模块加载器 CommonJs / AMD / UMD / ES6-爱代码爱编程

ES6 Modue 规范:JavaScript 语言标准模块化方案,浏览器和服务器通用,模块功能主要由 export 和 import 两个命令构成。export 用于定义模块的对外接口,import 用于输入其他模块提供的功能。 CommonJS 规范:主要用于服务端的 JavaScript 模块化方案,Node.js 采用的就是这种方案,所以各种 N

ES6---Module 的加载实现-爱代码爱编程

ES6---Module 的加载实现 一、浏览器加载加载规则二、ES6 模块与 CommonJS 模块的差异 一、浏览器加载 HTML 网页中,浏览器通过< script >标签加载 JavaScript 脚本。由于浏览器脚本的默认语言是 JavaScript,因此type="application/ja

CommonJS与 ES6 Module模块规范入门-爱代码爱编程

CommonJS与 ES6 Module模块规范入门 说明一、概述二、CommonJS(1)安装依赖(1)导出(2)导入(3)打包使用三、ES6 Module(1)导出(2)导入(3)使用 说明 更新时间:2022-02-06 本文主要基于CommonJS与 ES6 Module两种模块规范进行简单的梳理,同时结合了网上的很多相关教程,本文

ES6模块加载方案 CommonJS和AMD ES6和CommonJS-爱代码爱编程

目录 CommonJS CommonJS和AMD的对比 ES6和CommonJS  改成ES6 exports和module.exports  CommonJS 每个文件就是一个模块,有自己的作用域。在一个文件里面定义的变量、函数、类,都是私有的,对其他文件不可见;CommonJS规范规定,每个模块内部,module变量代表当前模块。

js模块化——commonjs amd cmd umd es6 module 比较_希文gershwin的博客-爱代码爱编程

1、CommonJS 是服务器模块的规范,Node.js采用了这个规范。 根据 CommonJS 规范,一个单独的文件就是一个模块,每一个模块都是一个单独的作用域,在一个文件定义的变量(还包括函数和类),都是私有的,对其他文件是不可见的。 CommonJS规范加载模块是同步的,也就是说,只有加载完成,才能执行后面的操作。 2、AMD AMD =

es6模块化+commonjs_不见长安见晨雾的博客-爱代码爱编程

ES6 模块化简介 在ES6模块化规范诞生之前,JavaScript社区已经尝试提出了AMD、CMD、CommonJS等模块化规范。 但是,这些由社区提出的模块化标准,有一定的差异性和局限性,并不是浏览器与服务器通用的模块化标准。例如: AMD和CMD适用于浏览器端的JavaScript模块化CommonJS适用于服务器端的JavaScript模块化

【vue.js】使用高德地图选择省市区后,再点击确认当前选择的位置_萌村村花杨小花的博客-爱代码爱编程

成品展示 前期准备 先去高德开放平台申请一个web端的key。 2022年后申请的key,必须和它生成的secret一起使用。 可使用服务选择web端 在vue项目中,可以通过直接引入js文件,也可以安装vu

es6与commonjs的模块化加载_commonjs 先转换成es6模块再带入-爱代码爱编程

两个差异 CommonJS 模块输出的是一个值的拷贝,ES6 模块输出的是值的引用。 什么是值的拷贝,值的引用?所谓值的拷贝,是在栈内存当中实现的,是一个复制的过程,复制之后两个值互不影响值的引用,是在堆内存当中实现的,

es6模块化and commonjs模块化-爱代码爱编程

1.ES6模块化规范  2.CommonJS模块化 4.CommonJS模块化 CommonJS 模块就是对象,输入时必须查找对象属性。 模块化对象 Node内部提供一个Module构建函数。所有模块都是Module的实例。每个模块内部,都有一个module对象,代表当前模块。它有以下属性。module.id 模块的识别符,通常是

[前端基础] javascript 进阶篇-爱代码爱编程

封装 Ajax ajax 可以无需刷新页面与服务器进行通讯,允许根据用户事件来更新部分页面内容。 readyStatus 的值: 0:未初始化1:启动;已经调用open()方法,但尚未调用send()方法。2:发送;已