JS中ESModule和commonjs介绍及使用区别

 更新时间:2022年07月26日 08:54:33   作者:​ Larixs​  
这篇文章主要介绍了JS中ESModule和commonjs介绍及使用区别,文章围绕主题展开详细的内容介绍,具有一定的参考价值,需要的朋友可以参考一下

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区别

语法:

exportsmodule.exportsrequire 是Node.js模块系统关键字。

exportexport defaultimport 则是ES6模块系统的关键字:

原理:

exportsmodule.exports导出的模块为值复制。

exportexport default为引用复制。

时机:

ES Module静态加载是编译时确定,ES Module动态加载是运行时确定。

CommonJS是运行时确定。

到此这篇关于JS中ESModule和commonjs介绍及使用区别的文章就介绍到这了,更多相关JS ESModule和commonjs 内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 详解JavaScript中Canvas的高级绘图和动画技术

    详解JavaScript中Canvas的高级绘图和动画技术

    JavaScript中的Canvas 是一个强大的 HTML5 元素,允许你通过编程方式创建图形、绘制图像和实现复杂的动画效果,在本文中,我们将深入探讨 JavaScript Canvas 的高级绘图和动画技术,并提供一个复杂的案例,以展示其潜力,需要的朋友可以参考下
    2023-10-10
  • 微信小程序实现文字滚动

    微信小程序实现文字滚动

    这篇文章主要为大家详细介绍了微信小程序实现文字滚动,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-03-03
  • JS打印彩色菱形的实例代码

    JS打印彩色菱形的实例代码

    本文通过一段简单的实例代码给大家介绍js实现打印彩色菱形的方法,非常不错,具有一定的参考借鉴价值,需要的朋友参考下吧
    2018-08-08
  • javascript数据类型详解

    javascript数据类型详解

    本文介绍了对javascript数据类型;隐式转换 (+ 和 -,== 和 ===);包装对象等相关知识进行详细介绍,具有很好的参考价值,下面跟着小编一起来看下吧
    2017-02-02
  • 学习drag and drop js实现代码经典之作

    学习drag and drop js实现代码经典之作

    今天读John Resig的Pro Javascript Techniques时候看到他书上给的一个关于drag and drop的例子, 合上书本自己写一个简化版本的。大约20分钟完成, 没有考虑兼容firefox。整个代码封装成一个对象 也是借鉴书中的风格。我觉得很好。
    2009-04-04
  • JS中引用百度地图并将百度地图的logo和信息去掉

    JS中引用百度地图并将百度地图的logo和信息去掉

    采用CSS覆盖的方法就可以了,但是官方是不允许这么做的,具体实现如下,感兴趣的朋友可以参考下
    2013-09-09
  • JavaScript模板引擎用法实例

    JavaScript模板引擎用法实例

    这篇文章主要介绍了JavaScript模板引擎用法,涉及javascript实现模板的定义与字符替换的相关技巧,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-07-07
  • JavaScript阻止回车提交表单的方法

    JavaScript阻止回车提交表单的方法

    如何防止回车(enter)键提交表单,其实很简单,就一句话。onkeydown="if(event.keyCode==13)return false;"把这句写在from标签里面就好了
    2015-12-12
  • JavaScript中DOM详解

    JavaScript中DOM详解

    这篇文章主要介绍了jQuery 中DOM 操作详解,以及在火狐和IE之间的13点JavaScript差异,需要的朋友可以参考下
    2015-04-04
  • HTML与javascript常碰到的编码问题

    HTML与javascript常碰到的编码问题

    在日常的前端开发工作中,我们会经常的与HTML、javascript、css等语言打交道,和一门真正的语言一样,计算机语言也有它的字母表、语法、词法、编码方式等
    2008-12-12

最新评论