ES6与CommonJS中的模块处理

news/2024/7/17 19:25:03

ES6和CommonJS都有自己的一套处理模块化代码的措施,即JS文件之间的相互引用。

为了方便两种方式的测试,使用nodejs的环境进行测试

CommonJS的模块处理

使用require来引入其他模块的代码,使用module.exports来引出

// exportDemo.js
count = 1;
module.exports.count = count;
module.exports.Hello = function() {
  var name;
  this.setName = function(newName) {
    name = newName;
  }
  this.sayHello = function() {
    console.log("hello Mr." + name);
  }
  this.getId = function() {
    return count++
  }
}
复制代码
// requireDemo.js
var {Hello} = require("./exportDemo")
var hello = new Hello();

hello.setName("Blank");
hello.sayHello();
复制代码

在终端执行node requireDemo.js,返回结果为'hello Mr.Blank'

导出的Hello函数是原函数的一次拷贝,修改Hello函数的属性值不会对其他require的地方造成影响

var { Hello, count } = require('./exportDemo')
var hello = new Hello();
// 让count自增
console.log(hello.getId());
console.log(hello.getId());
// 发现获取的count还是原值
console.log(count)

// 真正的count其实是已经改了的
var newHello = new Hello();
console.log(newHello.getId())

var { Hello: newHello, count: newCount } = require('./exportDemo')
console.log(newCount, 'newCount');
// 再次require,取得的newHello和之前require的Hello指向同一个拷贝
console.log(newHello === Hello) 
复制代码

ES6的模块处理

nodejs中运行ES6风格的代码

nodejs默认是不支持ES6的模块处理方案的。

但是在8.5.0之后,ES6代码的文件格式定为mjs后,可使用node --experimental-modules xxx.mjs运行。

// exportDemo.mjs
export let a = 1;
复制代码
// importDemo.mjs
import {a} from './exportDemo.mjs'
console.log(a)
复制代码

与CommonJS模块处理的区别

  • CommonJS 模块输出的是一个值的拷贝(已在上一章验证),ES6 模块输出的是值的引用。

    // exportDemo.mjs
    export let counter = 1;
    export function incCounter() {
      counter ++;
    }
    复制代码
    // importDemo.mjs
    import { counter, incCounter } from './exportDemo.mjs'
    
    incCounter();
    console.log(counter)		// 打印结果为2,而不是初始值的1
    复制代码
  • CommonJS模块是运行时加载,ES6模块是编译时输出接口

    • Nodejs此类的运行环境会在一个闭包中运行CommonJS模块代码

      (function(exports, require, module, __filename, __dirname) {
      // Module code actually lives in here
      });
      复制代码
    • ES6 模块不会缓存运行结果,而是动态地去被加载的模块取值,并且变量总是绑定其所在的模块。

      // exportDemo.mjs
      export let a = 1;
      export const b = 2;
      export let obj = {};
      
      // importDemo.mjs
      import { a, b } from './exportDemo.mjs'
      console.log(a, b)
      a = 1 // 报错,TypeError: Assignment to constant variable,export出来的值是一个只读引用
      obj.x = 1	// 可以改变属性值
      复制代码

      在ES6模块中我们更多地要去考虑语法的问题

export default

有时候我们会在代码发现export default obj的用法,那么这个default是用来干嘛的?

default是ES6引入的与export配套使用的关键字,用来给匿名对象、匿名函数设置默认的名字用的

export出来的值必须要有一个命名,否则从语法层次便会报错

让我们看一下以下几个会报错的错误例子

  • export匿名对象

    export { x: 1 }	// 报错,SyntaxError:Unexpected token,这是一个编译阶段的错误
    
    // 正确写法
    export default { x: 1 }
    复制代码
  • export匿名函数

    export function() {}	// 报错,SyntaxError: Unexpected token (
    
    // 正确写法
    export default function() {}
    复制代码

循环引用(recycling loading)

在复杂的模块中,可能会出现模块间的互相引用

commonJS的循环引用运行机制

// a.js
exports.loaded = false;
var b = require('./b.js')
console.log("b in a is " + JSON.stringify(b))
exports.loaded = true;
console.log("a complete")
复制代码
// b.js
exports.loaded = false;
var a = require('./a.js')
console.log("a in b is " + JSON.stringify(a))
exports.loaded = true;
console.log("b complete")
复制代码
// main.js
var a = require('./a.js')
var b = require('./b.js')

console.log("a in main is" + JSON.stringify(a))
console.log("b in main is" + JSON.stringify(b))
复制代码

执行指令nodejs main.js

时序图下的执行步骤分解图如下所示:

ES6的循环引用运行机制

  • 一个会报错的例子
// a.mjs
import { bar } from './b.mjs'

console.log(bar);
export let foo = 'foo from a.mjs'
复制代码
// b.mjs
import { foo } from './a.mjs'

console.log(foo)

export let bar = 'bar from b.mjs'
复制代码
// main.mjs
import { foo } from './a.mjs'
import { bar } from './b.mjs'
复制代码

node main.mjs

时序图下的执行步骤分解图如下所示:

ES6的循环引用要特别注意变量是否已被声明,若未被声明的块级作用域变量被其他模块引用时,会报错。

  • 改进方案:循环引用中尽量去export可以提前确定的值(例如函数),其实我们总是希望去引用模块执行完全后最终确定的变量

    // a.mjs
    import { bar } from './b.mjs'
    
    console.log(bar());
    export function foo() {
        return 'foo from a.mjs'
    }
    复制代码
    // b.mjs
    import { foo } from './a.mjs'
    console.log(foo());
    export function bar() {
        return 'bar from b.mjs'
    }
    复制代码
    // main.mjs
    import { foo } from './a.mjs'
    import { bar } from './b.mjs'
    复制代码

    node main.mjs

    返回结果:

    foo from a.mjs
    bar from b.mjs
    复制代码

    时序图下的执行步骤分解图如下所示:


http://www.niftyadmin.cn/n/3723644.html

相关文章

通汇手机为何卖得那么红火

通汇手机连锁去年销量又高居粤西地区榜首 通汇手机为何卖得那么红火 今年1月,国内权威调查机构赛诺公司发布国内各地级市去年行货手机销售相关数据,茂名地区2005年10月份的行货手机总销量约为13500台,其中,通汇手机连锁当月份销量…

JS中变量名和函数名重名

2019独角兽企业重金招聘Python工程师标准>>> js是弱类型语言&#xff0c;所以变量声明这块肯定会有怪异的问题。 var a100; function a(){   console.log(a); } a();执行结果是&#xff1a; Uncaught TypeError: a is not a functionat <anonymous>:5:1看…

Delphi控制Excel

(一) 使用动态创建的方法首先创建 Excel 对象&#xff0c;使用ComObj:var ExcelApp: Variant;ExcelApp : CreateOleObject( Excel.Application );1) 显示当前窗口&#xff1a;ExcelApp.Visible : True;2) 更改 Excel 标题栏&#xff1a;ExcelApp.Caption : 应用程序调用 Micros…

Access安全吗?Access安全性之QA详解

Access安全吗&#xff1f;Access安全性之QA详解作者&#xff1a;Access911日期&#xff1a;2001-04-03原文地址&#xff1a;http://access911.net/old/study/a_oth002.htm 在写这篇文章前首先要感谢网友&#xff1a;松木、zengwb、秋天、4432&#xff0c;谢谢他们围绕Access安全…

【很好,很和谐】蒙骗了CCTV 人民网 凤凰网 网易 新浪的 特大假新闻 学生网站系统 007OS 取代Windows操作系统

事态发展 &#xff1a;假新闻 已经被各大媒体转载 007os相关新闻: 大三学生研发软件卖200万元成富豪(图)       cctv 学生所创办网站被亿聚网以200万价格收购(图) 央视国际 大学生研发新计算机操作系统亿聚200万收购    人民网 亿聚网200万收购华工学生个人网站007os …

js正则及常用方法函数总结

js正则及常用方法函数总结 一、总结 一句话总结&#xff1a;两种&#xff0c;字符串方法和正则对象方法。 二、js正则及常用方法函数总结 正则表达式作为一种匹配处理字符串的利器在很多语言中都得到了广泛实现和应用&#xff0c;web开发本质上是处理字符串&#xff08;服务端接…

寻找最短的跨站代码(by jmdcw)

那天剑心问我&#xff0c;最短的跨站语句是多少&#xff1f;要放在以前&#xff0c;我一定会这样想&#xff0c;正常的跨站代码&#xff1a;<script>alert("a")</script> &#xff0c;查一下&#xff0c;一共27个字符。嘿嘿&#xff0c;不过&#xff0c;…

从React组件划分的纠结到总结

在实际开发项目中&#xff0c;我将所有的React组件划分为容器组件和展示组件&#xff0c;展示组件其实就是一个纯函数组件&#xff0c;没有任何副作用&#xff0c;基本都是PureComponent。但是突然&#xff0c;出现了这么一个问题&#xff1a; 我有一个浮层组件Layer&#xff0…