一个小问题引发的思考 —— ES6 module scope

2023-05-25  本文已影响0人  麦西的西

引子

首先,看这样一个问题,有两个文件fun.jsmain.js:

// fun.js
let a = 1;

export default function () {
  a = a + 1;
  console.log(a);
}
// main.js
import fun from './fun.js';

fun();
fun();
fun();

执行结果是什么?

2
3
4

答案很简单。这不就相当于直接把 fun.js 里的函数粘贴到 main.js 里嘛?

let a = 1;

function fun() {
  a = a + 1;
  console.log(a);
}

fun();
fun();
fun();

然而问题来了,a 存储在哪个作用域?window 上?

全局?

我打印了下:

// main.js
import fun from './fun.js';

fun();
fun();
fun();

console.log(a);

结果 a 的值是undefined

当然 let 修饰的变量是块级作用域,不会放到 window 作用域。于是我修改了下:

// fun.js
var a = 1;

export default function () {
  a = a + 1;
  console.log(a);
}

然后打印 a,依然是 undefined

闭包?

然后有人说是形成了闭包,所以它没有在 window 上,且一直存储在内存中。但是不存在函数嵌套的情况,好像不能构成闭包的条件。

判断一下就好了。但是我怎么来判断是不是闭包呢?

用 webpack 打包成一个文件,再单独 debug 这个文件中的代码。于是,我用 webpack 打包。打包后 debug 如下:

webpack-closure.jpeg

果然是闭包。

不对,webpack 相当于把 export/import 手动实现了一遍。export被它处理成了一个函数。这样就构成了闭包的条件。

我为什么不直接 debug 看看这个变量 a 到底是何方神圣呢?果然还是走了弯路。

ES6 module scope

使用 chrome 直接 debugfun.js,然后在 scope 里发现了一个东西,module

module-scope.jpeg

哦,原来如此,我赶紧搜索栏下 module scope,果然有人跟我有相同的疑问:

https://stackoverflow.com/questions/30287977/es6-module-scope

可以这样理解, js 的作用域分为:

模块作用域的底层是怎样我们不知道,但如果让我们实现一个模块作用域,那自然是通过函数来隔离作用域。

function moduleFun() {
  var a = 1;
  return function fun() {
    a = a + 1;
    console.log(a);
  };
}

const fun = moduleFun();

fun();
fun();
fun();

也就跟 webpack 思路一样,所以会构成闭包也是理所当然了。

参考文档

https://stackoverflow.com/questions/30287977/es6-module-scope

上一篇下一篇

猜你喜欢

热点阅读