相关代码地址:https://github.com/blank-x/blog-code/tree/main/1-module

引入变量

es6 导入变量只是一个符号链接,是个常量,类似于const 声明;

<script type="module">
import mod1 from './module1.js'
console.log(mod1);
mod1 = 12 // 类似于const 声明 会报错误
</script>

commonjs 导入变量没有这样的限制

模块输出

es6 模块输出的是一个值的引用,引用随原始值变化而变化

// index.html
<script type="module">
import {b} from './module1.js'
console.log(b); // 12
setTimeout(()=>{
console.log(b); // 13
},1000)
</script> // module1.js
setTimeout(()=>{
b++
},500)
export let b = 12
// 上面的例子中两次打印的值不同,说明es6输出的不是值的拷贝,更像是一个引用、指针、链接,能够动态改变的。

commonjs 导出的是一个普通对象,是模块的浅拷贝

exports导出的是一个对象,这个对象是通过运算得出的结果,因为是浅拷贝,如果其中包含的引用类数据,这个数据会被共享;

模块对象上有模块的相关信息:

  • module.id 模块的识别符,通常是带有绝对路径的模块文件名。
  • module.filename 模块的文件名,带有绝对路径。
  • module.loaded 返回一个布尔值,表示模块是否已经完成加载。
  • module.parent 返回一个对象,表示调用该模块的模块。
  • module.children 返回一个数组,表示该模块要用到的其他模块。
  • module.exports 表示模块对外输出的值。

module.exports是当前模块对外输出的接口,其他文件加载该模块,其实是读取module.exports;

所以一般说commonjs只能导出单个值,通过解构赋值获取其中的方法或者属性;

语法要求

es6

  1. import export语法只能写在顶层,写在条件判断里的import会报错;
  2. 自动采用严格模式;

commonjs没有对应的限制;

静态加载

es6

在执行之前,浏览器会做静态分析编译,同时通过export输出接口;export 语法是静态数据输出的关键,是对外的接口;

commonjs

运行时加载

异步加载

es6

如果是在浏览器中,通过script type="module" 加载远程模块, 即等到整个页面渲染完,再执行模块脚本,等同于打开了<script>标签的defer属性。

<script>标签的async属性也可以打开,这时只要加载完成,渲染引擎就会中断渲染立即执行。执行完成后,再恢复渲染。

commonjs

没有异步加载的概念

循环加载

es6

在加载之前有一个静态编译的过程,期间会把输出的接口给确定下来,当被循环加载的时候,导出这些确定的接口,不需要再次被编译和加载;

es6对模块只生成一个引用,所以并不存在循环加载;但是需要我们自己保证能够加载到数据,比如下面打印出了undefined;

// a.js
import {bar} from './circle-2.js';
console.log('a.js');
console.log(bar);
export var foo = 'foo'; // b.js
import {foo} from './circle-1.js';
console.log('b.js');
console.log(foo);
export var bar = 'bar';
// b.js
// circle-2.js:3 undefined
// circle-1.js:2 a.js
// circle-1.js:3 bar

Commonjs

输出已经执行的部分;

在循环加载的过程中,其实就是类似缓存在其中起的作用;nodejs中加载过的模块缓存在require.cache中,

// 直接在nodejs中执行这个文件 commonjs-entry.js
var b = {f:12}
module.exports = b
var commonjs1 = require('./commonjs-1')
console.log(commonjs1); // // { prop1: 1, prop2: 12 }
b.name = 1
console.log(b); // { f: 12, name: 1 } // commonjs-1.js
var a = {prop1:1}
module.exports = a
var result1 = require('./commonjs-entry')
console.log(result1); // { f: 12 }
a.prop2 = 12

ES6 import 会自动提到模块顶端

// es6-mod1.mjs
console.log(111);
import {bar} from './es6-mod2.mjs'; // es6-mod2.mjs
console.log('222'); // 打印顺序
// 222
// 111

ES6 加载 CommonJS 模块

这是在nodejs中允许的,只要使用node --experimental-modules 就可以正常加载了;

因为commonjs输出的是一个对象,不能被静态分析,只能整体加载 ,那么就不知道输出有哪些接口,最终像import {readfile} from 'fs' 这种代码在静态分析的时候自然会报错;

// a.js
module.exports ={
foo: 1
}
// main.mjs
import baz from ' ./a';
// 等价于 import {default as baz} from './a' // terminal
node --experimental-modules main.mjs
// { foo: 1 }
// { default: { foo: 1 } }

Commonjs 加载 es6 模块

在nodejs中commonjs模块是无法直接加载es6模块的;因为require在es6模块下不能使用。

webpack 打包中对es6 模块的处理

虽然es6中不能直接对import导出来的对象重新赋值,但是在前端开发过程中使用的webpack,重新赋值有什么不同呢?

结论:也会报错,但是错误的内容和原因不一样;



对下面的代码打包:

import Vue from 'vue'
console.log(Vue)
Vue = 12

结果:

var vue__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! vue */ "2b0e");
// 打包后的代码中变量Vue被替换如下:vue__WEBPACK_IMPORTED_MODULE_4__["default"];
console.log(vue__WEBPACK_IMPORTED_MODULE_4__["default"]);
Vue = 12; // 这行代码没有变化,没有替换成vue__WEBPACK_IMPORTED_MODULE_4__["default"] ,报错的就是这一行

报错原因是严格模式下全局变量未声明

es6 模块和commonjs规范模块的区别的更多相关文章

  1. es6模块与 commonJS规范的区别

    https://www.cnblogs.com/weblinda/p/6740833.html

  2. 关于CommonJS规范摘录

    CommonJS规范 1. 概述 为什么要用commonjs 模块化的目的: 减少循环依赖 减少耦合,提高了模块的复用率 有利于多人开发,提高开发的效率. 规避命名的冲突.全局变量的污染.有利于代码的 ...

  3. NodeJS新建服务器以及CommonJS规范

    1.什么是node.js?(1)Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境.Node.js 使用了一个事件驱动.非阻塞式 I/O 的模型,使其轻量又高效.( ...

  4. CommonJS规范(转)

    概述 CommonJS是服务器端模块的规范,Node.js采用了这个规范. 根据CommonJS规范,一个单独的文件就是一个模块.加载模块使用require方法,该方法读取一个文件并执行,最后返回文件 ...

  5. [摘抄] 3.AMD规范与CommonJS规范的兼容性

    3. AMD规范与CommonJS规范的兼容性 CommonJS规范加载模块是同步的,也就是说,只有加载完成,才能执行后面的操作. AMD规范则是非同步加载模块,允许指定回调函数. 由于Node.js ...

  6. CommonJS规范 by ranyifeng

    1,概述 CommonJS是服务器端模块的规范,Node.js采用了这个规范. 根据CommonJS规范,一个单独的文件就是一个模块.加载模块使用require方法,该方法读取一个文件并执行,最后返回 ...

  7. es6 模块与commonJS的区别

    在刚接触模块化开发的阶段,我总是容易将export.import.require等语法给弄混,今天索性记个笔记,将ES6 模块知识点理清楚 未接触ES6 模块时,模块开发方案常见的有CommonJS. ...

  8. ES6模块与CommonJS模块有什么区别?

    ES6 Module和CommonJS模块的区别: CommonJS是对模块的浅拷贝,ES6 Module是对模块的引用,即ES6 Module只存只读,不能改变其值,具体点就是指针指向不能变,类似c ...

  9. Javascript模块规范(CommonJS规范&&AMD规范)

    Javascript模块化编程(AMD&CommonJS) 前端模块化开发的价值:https://github.com/seajs/seajs/issues/547 模块的写法 查看 AMD规 ...

随机推荐

  1. UVA-10815 Andy's First Dictionary (非原创)

    10815 - Andy's First Dictionary Time limit: 3.000 seconds Problem B: Andy's First DictionaryTime lim ...

  2. Leetcode(53)-最大子序和

    给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和. 示例: 输入: [-2,1,-3,4,-1,2,1,-5,4], 输出: 6 解释: 连续子数组 ...

  3. NoSQL 数据库案例实战 -- MongoDB数据备份、恢复

    MySQL数据迁移到MongoDB数据库中 前言 一.数据备份 二.数据恢复 前言 本环境是基于 Centos 7.8 系统构建mongodb-enterprise-4.2.8学习环境具体构建,请参考 ...

  4. The best Fibonacci is achieved in js

    The best Fibonacci is achieved in js the best realized by using js 斐波那契数列 "use strict"; /* ...

  5. Swift 5.3

    Swift 5.3 https://swift.org/blog/ refs xgqfrms 2012-2020 www.cnblogs.com 发布文章使用:只允许注册用户才可以访问!

  6. 25_MySQL 数据操作语言:UPDATE语句

    -- UPDATE 把每个员工的编号和上司的编号都加1,用 ORDER BY 完成 UPDATE t_emp SET empno=empno+1,mgr=mgr+1 ORDER BY empno DE ...

  7. IntelliJ IDEA 还能画思维导图,果然最强 IDE!

    最近栈长发现 IntelliJ IDEA 居然还能画思维导图,太牛逼了! 当然这得借助 IDEA 的 UML 插件,因为它本身也是一个 UML 图,所以这篇就从 UML 图开撕,看 IDEA 怎么画思 ...

  8. 物联网网关开发:基于MQTT消息总线的设计过程(上)

    道哥的第 021 篇原创 目录 一.前言 二.网关的作用 2.1 指令转发 2.2 外网通信 2.3 协议转换 2.4 设备管理 2.5 边沿计算(自动化控制) 三.网关内部进程之间的通信 3.1 网 ...

  9. 程序员如何在VsCode上看基金?

    一 我是一个程序员. 代码是我的禁锢,基金是我的自由. 打破禁锢,奔向自由,也许只差几个定投. 有人说,买基金一定要心态好,要学会风险对冲,把8成的钱全仓买基金,剩余2成买意外身亡险,基金大涨就赚,基 ...

  10. Go benchmark 一清二楚

    前言 基准测试(benchmark)是 go testing 库提供的,用来度量程序性能,算法优劣的利器. 在日常生活中,我们使用速度 m/s(单位时间内物体移动的距离)大小来衡量一辆跑车的性能,同理 ...