我一直在reading about ES modules进行实验并偶然发现了一个我无法解释的案例:
// 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
我可以通过const
变量覆盖settings
值,但在main2.js
我不能(正如预期的那样)。
(理论上)问题是为什么在第一种情况下可以覆盖const
值?创建“只读视图”是否只是在常规对象上创建属性并破坏原始结构?
实际问题是从模块返回常量集合(或只读属性)的最有效方法是什么?我的想法是:
// settings.js
export default Object.freeze({
FOO: 42,
BAR: 5
});
有什么想法吗?
编辑:我正在使用巴贝尔。答案 0 :(得分:8)
另一个答案是错误的。
(理论上)问题是为什么在第一种情况下可以覆盖const值?
这实际上完全独立于const
。使用ES6模块语法,不允许从模块外部重新分配模块的导出值。 export let FOO;
或export var FOO;
也是如此。代码内部模块是唯一允许更改导出的东西。
在技术上做settings.FOO = 1
应该抛出异常,但大多数编译器目前都没有处理这个特殊的边缘情况。
举个例子,你可以做到
export var FOO;
export function setFoo(value){
FOO = value;
}
并且鉴于此,此是const
变得有用的原因,因为它与任何其他普通的JS代码相同。 FOO = value
如果被声明为export const FOO
则会失败,所以如果你的模块导出了一堆常量,那么执行export const FOO = 1, FOO2 = 2;
是导出常量的好方法,它只是那个巴别塔实际上并没有使它们永不变化。
答案 1 :(得分:1)
在此代码中
import * as settings from './settings';
settings.FOO = 1;
在上面的代码中,您不是直接分配常量变量,而是分配settings
中的克隆副本。
import * as settings from './settings';
^^^^^^^^^^^^
settings.FOO = 1;
但在下一个代码中并非如此
import {FOO, BAR} from './settings'
FOO = 1;
此处FOO
和BAR
是常量,您无法分配给它。