ES6 模块 - 为什么命名的 const 导出不是只读的



我一直在阅读有关 ES 模块和实验的信息,偶然发现了一个我无法解释的案例:

// settings.js
export const FOO = 42;
export const BAR= 5;
// main1.js
import * as settings from './settings';
settings.FOO = 1;
//main2.js
import {FOO, BAR} from './settings'
FOO = 1;

main1.js中,我能够通过settings变量覆盖const值,但在main2.js中我不能(如预期的那样(。

(理论上的(问题是,为什么在第一种情况下可以覆盖const值?创建"只读视图"是否只是在常规对象上创建属性并破坏原始结构?

实际的问题是,从模块返回常量(或只读属性(集合的最有效方法是什么?我想到的是:

// settings.js
export default Object.freeze({
FOO: 42,
BAR: 5
});

有什么想法吗?

编辑:我正在使用Babel。

另一个答案是不正确的。

(理论上的(问题是为什么在第一种情况下可以覆盖常量值?

这实际上完全独立于const。使用 ES6 模块语法时,不允许从模块外部重新分配模块的导出值。export let FOO;export var FOO;也是如此。模块中的代码是唯一允许更改导出的内容。

从技术上讲,执行settings.FOO = 1应该会引发异常,但大多数编译器目前不处理这种特定的边缘情况。

举个例子,你可以做

export var FOO;
export function setFoo(value){
FOO = value;
}

鉴于此,这就是const变得有用的时候,因为它与任何其他普通的 JS 代码相同。 如果声明为export const FOOFOO = value会失败,所以如果你的模块导出一堆常量,做export const FOO = 1, FOO2 = 2;是导出常量的好方法,只是 Babel 实际上并没有使它们不可变。

在此代码中

import * as settings from './settings';
settings.FOO = 1;

在上面的代码中,您不是直接分配给常量变量,而是在settings中分配了一个克隆的副本。

import * as settings from './settings';
^^^^^^^^^^^^
settings.FOO = 1;

但在下一个代码中

并非如此
import {FOO, BAR} from './settings'
FOO = 1;

这里的FOOBAR是常量,您无法分配给它。

最新更新