JS中ESModule和commonjs介绍及使用区别
作者:Larixs 发布时间:2023-10-20 22:23:51
ES Module
导出
仅导出
named exports: 命名导出,每次可以导出一个或者多个。
default exports: 默认导出,每次只能存在一个。
以上两者可以混合导出:
// 命名导出
export const b = 'b'
// 默认导出
export default {
a: 1
};
const c = 'c'
export { c }
// 以上内容会合并导出,即导出为: {b:'b', c:'c', default: {a:1}}
更多示例可以直接去看mdn
重导出(re-exporting / aggregating)
算是一个导入再导出的一个语法糖吧。
export {
default as function1,
function2,
} from 'bar.js';
// 等价于
import { default as function1, function2 } from 'bar.js';
export { function1, function2 };
然而这种语法是会报错的:
export DefaultExport from 'bar.js'; // Invalid
正确的语法应该是:
export { default as DefaultExport } from 'bar.js'; // valid
我猜是因为export 本身支持的export xxx这种语法必须是要导出一个对象,然而import xxx可能是任意类型,两者冲突了,所以从编译层面就不让这种语法生效会更好。
嵌入式脚本
嵌入式脚本不可以使用export。
引入
语法
import all exports:
import * as allVar
,所有导出内容,包含命名导出及默认导出。allVar会是一个对象,默认导出会作为allVar的key名为default对应的值。import named exports:
import {var1, var2}
,引入命名导出的部分。没找到,对应的值就为undefined。个人觉得可以看做是"import all exports"的解构语法。import default exports:
import defaultVar
,引入默认导出的部分。import side effects:
import "xxx./js"
,仅运行这个js,可能是为了获取其副作用。
// test.js
export const b = 'b' // 命名导出
export default { // 默认导出
a: 1
};
// index.js
import { b, default as _defaultModule } from './test.js'
import defaultModule from './test.js'
import * as allModule from './test.js'
console.log('name export', b) // 'b'
console.log('default export', defaultModule) // {a:1}
console.log(_defaultModule === defaultModule) // true
console.log('all export', allModule) // {b:'b', default: {a:1}}
一个之前老记错的case
// test.js
export default { // 默认导出
a: 1
};
// index.js
import { a } from './test.js'
console.log('name export', a) // undefined
// index.js
import defaultModule from './test.js'
import * as allModule from './test.js'
console.log('default export', defaultModule) // {a:1}
console.log('all export', allModule) // {default: {a:1}}
嵌入式脚本
嵌入式脚本引入modules时,需要在script上增加 type="module"。
特点
live bindings:
通过export在mdn上的解释,export导出的是live bindings,再根据其他文章综合判断,应该是引用的意思。即export导出的是引用。
模块内的值更新了之后,所有使用export导出值的地方都能使用最新值。
read-only:通过import在mdn上的解释,import使用的是通过export导出的不可修改的引用。
strict-mode:被引入的模块都会以严格模式运行。
静态引入、动态引入
import x from
这种语法有syntactic rigid,需要编译时置于顶部且无法做到动态引入加载。如果需要动态引入,则需要import ()
语法。有趣的是,在mdn上,前者分类到了 Statements & declarations, 后者分类到了 Expressions & operators。这俩是根据什么分类的呢?
true && import test from "./a.js";
// SyntaxError: import can only be used in import() or import.meta
// 这里应该是把import当成了动态引入而报错
示例:
// a.js
const test = {
a: 1
};
export default test;
// 改动模块内部的值
setTimeout(() => {
test.a = 2;
}, 1000);
// index.js
import test from './index.js'
/* live bindings */
console.log(test) // {a:1}
setTimeout(()=>{
console.log(test) // {a:2}
}, 2000)
/* read-only */
test= { a: 3 } // 报错, Error: "test" is read-only.
/* syntactically rigid */
if(true){
import test from './index.js' // 报错, SyntaxError: 'import' and 'export' may only appear at the top level
}
commonJS
导出
在 Node.js 模块系统中,每个文件都被视为独立的模块。模块导入导出实际是由nodejs的模块封装器实现,通过为module.exports
分配新的值来实现导出具体内容。
module.exports
有个简写变量exports
,其实就是个引用复制。exports作用域只限于模块文件内部。 原理类似于:
// nodejs内部
exports = module.exports
console.log(exports, module.exports) // {}, {}
console.log(exports === module.exports) // true
注意:nodejs实际导出的是module.exports,以下几种经典case单独看一下:
case1:
// ✅使用exports
exports.a = xxx
console.log(exports === module.exports) // true
// ✅等价于
module.exports.a = xxx
case2:
// ✅这么写可以导出,最终导出的是{a:'1'}
module.exports = {a:'1'}
console.log(exports, module.exports) // {}, {a:'1'}
console.log(exports === module.exports) // false
// ❌不会将{a:'1'}导出,最终导出的是{}
exports = {a:'1'}
console.log(exports, module.exports) // {a:'1'}, {}
console.log(exports === module.exports) // false
引入
通过require语法引入:
// a是test.js里module.exports导出的部分
const a = require('./test.js')
原理伪代码:
function require(/* ... */) {
const module = { exports: {} };
((module, exports) => {
// Module code here. In this example, define a function.
function someFunc() {}
exports = someFunc;
// At this point, exports is no longer a shortcut to module.exports, and
// this module will still export an empty default object.
module.exports = someFunc;
// At this point, the module will now export someFunc, instead of the
// default object.
})(module, module.exports);
return module.exports;
}
特点
值拷贝
// test.js
let test = {a:'1'}
setTimeout(()=>{
test = {a:'2'}
},1000)
module.exports = test
// index.js
const test1 = require('./test.js')
console.log(test1) // {a:1}
setTimeout(()=>{
console.log(test1) // {a:1}
},2000)
ES Module和 commonJS区别
语法:
exports
、module.exports
和require
是Node.js模块系统关键字。
export
、export default
和import
则是ES6模块系统的关键字:
原理:
exports
、module.exports
导出的模块为值复制。
export
、export default
为引用复制。
时机:
ES Module静态加载是编译时确定,ES Module动态加载是运行时确定。
CommonJS是运行时确定。
来源:https://juejin.cn/post/7124167499221827614
猜你喜欢
- JavaScript中有很多内部属性和方法,在大多数情况下,只有JavaScript引擎才可以访问,但不论什么都是有特例的,在这里就是指Mo
- asp定时生成静态HTML的代码,对于缓解服务器压力有很大帮主,需要的朋友可以参考下。<% '判断是否要生成新的HT
- SQL Server与Oracle、DB2的优劣对比:1.开放性:SQL Server只能在Windows上运行,没有丝毫的开放性,操作系统
- 作者:AngelGavin 出处:CSDN一般问题什么是 XML?可扩展标记语言 (XML) 是 Web 上的数据通用语言。它使
- CSS 中的 position 属性可以很容易的将指定的元素定位到理想的位置。但在使用这一属性时需要注意,尤其是在表格元素中。为了说明此问题
- 最近一直在“深山老林”中修炼“支付宝新版收银台”,经历了白板设计,视觉设计,前端开发,前后端联调各个阶段。点点滴滴……重点谈谈对交互设计的感
- JS在firefox中的兼容性问题,自己也经常遇到.此文是网上资料,不过时间较久不记得原址了...1. document.form.item
- 顽固的Select下拉列表,一般很难用css来控制样式下面使用了js来美化select<!DOCTYPE html PUBLIC &q
- 参数strSQL 要导出的SQL查询语句strFields 字段名称列表,如果为空字符,则使用SQL语句中的字段名用法示例:1:export
- 关于Mysql的触发器,基本上每个Mysql教程里都有讲到,但是我发现那些教程里讲的都是如何处理其他表的数据。在Mysql中写触发器操作本表
- 看了下传统的方法,觉得不好,太麻烦。自己重写了个,思路比较新。这个函数的优点是html代码可以很简洁,使用图片也可以很少,只需要两张图片。事
- js 代码中经常会碰到 undefined 这种错误,下面本文分享一下为什么会发生这种错误以及如何处理这种错误,js 中如果通过 var 声
- 阅读上一章:Chapter 9 精简标签Part 2: Simplebits Of Style 简短精悍的样式Chap
- 通常,当一个页面有太多信息要显示,而一页塞又不下所有信。为了请求速度、美观以及其他的各种理由,分页就会被我们请过来。让我们的用户可以选择是否
- 本文实例为大家分享了微信小程序上传视频,供大家参考,具体内容如下微信开发者工具需要安装ffmpeg环境才能正常使用下面的官方方法。1、调用官
- 对网站的LOGO设计做了一些归纳,希望得到批评,发现写的太长了,又不忍心删减,就分成两部分了,第一部分是有关设计基础的。第二部分是关于网站L
- 本文实例讲述了PHP基于迭代实现文件夹复制、删除、查看大小等操作的方法。分享给大家供大家参考,具体如下:前面一篇 PHP递归实现文件夹的复制
- 基本思路使用GDAL创建Shapefile数据的基本步骤如下:使用osgeo.ogr.Driver的CreateDataSource()方法
- 1、设置字体、风格代码主题选择Monokai会是彩色的代码。2、配置CI代码提示<1>下载代码提示项目:https://gith
- XMLHttpRequest 最近在 W3C 标准之路上又迈进了一步,W3C Web API&nbs