【问题标题】:ES6 Modules - why named const exports are not read onlyES6 模块 - 为什么命名的 const 导出不是只读的
【发布时间】:2017-08-22 12:16:07
【问题描述】:

我一直在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 中,我可以通过settings 变量覆盖const 值,但在main2.js 中我不能(如预期的那样)。

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

实际问题是从模块返回一组常量(或只读属性)的最有效方法是什么?我的想法是这样的:

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

有什么想法吗?

编辑:我正在使用 Babel。

【问题讨论】:

  • 你从来没有在你的问题中说,你使用的是什么模块实现?因为这个问题的答案完全取决于你使用的编译器。
  • @loganfsmyth 是 Babel,你认为这是实现中的错误吗?
  • 我认为我们没有针对它的特定错误,尽管它绝对是一个已知的缺陷。如果您想提交,欢迎提交。

标签: javascript ecmascript-6 babeljs es6-modules


【解决方案1】:

另一个答案不正确。

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

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

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

例如,你可以这样做

export var FOO;

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

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

【讨论】:

  • 这是我想走的原始方式,但在测试时我意识到在执行import * as settings时这些值被覆盖了
【解决方案2】:

在这段代码中

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 是常量,不能赋值给它。

【讨论】:

  • "你不是直接分配给常量变量,而是设置中的克隆副本" Babel 就是这种情况,但这不是 ES 规范中定义的行为。 settings.FOO = 1; 在现实中应该会抛出异常。
猜你喜欢
  • 2018-10-02
  • 1970-01-01
  • 2011-08-12
  • 1970-01-01
  • 2017-05-16
  • 1970-01-01
  • 1970-01-01
  • 2015-10-24
  • 2016-04-07
相关资源
最近更新 更多