前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >ES6中的模块

ES6中的模块

作者头像
零式的天空
发布2022-03-21 20:58:03
2230
发布2022-03-21 20:58:03
举报
文章被收录于专栏:零域Blog零域Blog

最近在做项目的时候发现在一个模块导出的时候是返回一个NEW以后实例化的对象,在其他地方使用的是同一个对象(一直以为是不用的对象,每次导入都是一个新的。。。还是太菜)。

在网上了解了ES6模块的一个基本机制,所以记录一下笔记。

ES6中模块不会重复执行

一个模块无论被多少个地方引用,引用多少次,模块内部始终只执行一次。

ES6中模块输出值的引用

在ES6中,导出输出的值会动态关联模块中的值:

代码语言:javascript
复制
// count.js
let count = 0
let add = function () {
  count ++
}
export { count, add }

// a.js
import { count, add } from "./count.js"
console.log(count) // 0
add()
console.log(count) // 1

// b.js
import { count } from "./count.js"
console.log(count) // 1

count的值是会动态变化的。

ES6模块循环依赖

import 会优先执行,跟位置无关

代码语言:javascript
复制
// a.js
console.log("a.js")
import { b } from "./b"

// b.js
export const b = "B"
console.log("b.js被执行")

// 结果
// b.js被执行
// a.js

import被JS引擎静态分析,会被提到模块的最前面,优先于模块中的其他部分的执行。

代码语言:javascript
复制
// a.js
console.log(`Start A:`)

import { b } from "./b"

export const a = "AAA"

console.log(`A正在获取数据b: ${b}`)

console.log(`End A:`)

// b.js
console.log(`Start B:`)

import { a } from "./a"

export const b = "BBB"

console.log(`B正在获取数据a: ${a}`)

setTimeout(() => {
  console.log("end..")
})

console.log(`End B:`)

// 执行a.js
// 结果:

// Start B:
// B正在获取数据a: ?developer/article/1960645/undefined
// End B:
// Start A:
// A正在获取数据b: BBB
// End A:
// end..

// main.js
import { a } from "./a"
import { b } from "./b"
console.log(a)
console.log(b)

// 执行a.js
// 结果:

// Start B:
// B正在获取数据a: ?developer/article/1960645/undefined
// End B:
// Start A:
// A正在获取数据b: BBB
// End A:
// end..
// AAA
// BBB

(CommonJS)首先a.js加载b.js,此时a.js代码暂停在这里,执行加载b.js,在b.js中又加载a.js,但是a.js并没有加载完,所以获取到?developer/article/1960645/undefined,然后继续执行完以后,回到a.js正常执行。

(ES6) 首先a.js加载b.js,所以先执行b.js,而b.js又去加载a.js,这时候由于a.js已经开始执行了,所以不会重复执行,而是继续执行b.js,又a.js还未执行完,所以b.js获取到值是?developer/article/1960645/undefined,然后继续执行完以后,回到a.js正常执行。

CommonJS 和 ES6 的这个加载描述是在网上查阅的,还不是很懂,感觉两种方式的行为都是一样的啊= =!! 感觉CommonJS的加载方式套用在ES6,ES6的加载方式套用在CommonJS都能说的通。。CommonJS模块不也是只会加载一次嘛,套用在ES6感觉都没毛病。。。

在main.js中执行,得出并不会再去执行第二行代码b.js,原因是在执行a.js时b.js已经被加载,模块不会被重复加载

一个关于动态引用的例子:
代码语言:javascript
复制
// a.js
import {bar} from './b.js';
export function foo() {
  console.log('foo');
  bar();
  console.log('执行完毕');
}
foo();
 
// b.js
import {foo} from './a.js';
export function bar() {
  console.log('bar');
  if (Math.random() > 0.5) {
    foo();
  }
}

按照CommonJS规范,上面的代码是无法执行的。a先加载b,然后b又加载a,这时a还没有任何执行结果,所以输出结果为null,即对于b.js来说,变量foo的值等于null,后面的foo()就会报错。

但是,ES6可以执行上面的代码,a.js之所以能够执行,原因就在于ES6加载的变量都是动态引用其所在模块的。只要引用存在,代码就能执行。

会到问题到最开始,在导出时返回new对象到操作,只有在第一次加载的时候,会执行模块中的代码,返回一个实例化以后的对象,以后的每次导入,都是第一次的结果,并不会重新在去执行一次模块的代码。

代码语言:javascript
复制
// obj.js
class TestObj {
  this.name = "";

  setName = (name) => {
    this.name = name;
  }

  print = () => {
    console.log(this.name);
  }
}
export default new TestObj();

// a.js
import TestObj from "./TestObj"
TestObj.setName("Sukoshi")
console.log(TestObj.print()) // Sukoshi

// b.js
import TestObj from "./TestObj"
console.log(TestObj.print()) // Sukoshi
本文参与?腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2020-03-07,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客?前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与?腾讯云自媒体分享计划? ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • ES6中模块不会重复执行
  • ES6中模块输出值的引用
  • ES6模块循环依赖
  • 一个关于动态引用的例子:
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
http://www.vxiaotou.com