javascript - 导入值与其导出值断开连接是否仍然是只读的?

标签 javascript ecmascript-6 es6-modules

给定以下模块结构:

// module A:
export let a = 1; // named export
export function inc() { a++; } // named export

// module B:
let b = 1;
export default b; // default export (equivalent to `export default 1`)
export function inc() { b++; } // named export

// module C:
let c = {};
export default c; // default export

// module E:
import a, {inc as incA} from "./A";
import b, {inc as incB} from "./B";
import c from "./C";

incA();
console.log(a); // logs 2, because "a" has a live connection to the export value
a++; // Error (because a is a live read-only view on the export)

incB();
console.log(b); // logs 1, because "b" is disconnected from the export value
b++; // Does this throw an error as well?

c.prop = true; // I think mutations are always allowed, right?
c = {}; // but are reassignment allowed too?

如果我有一个表达式的默认导出(export default bexport default 1),相应的导入将与该导出值断开连接。考虑到这一点,这样的导入是否仍然是只读的,也就是说,我可以重新分配 ac 吗?

最佳答案

导入绑定(bind)始终是只读的,请参阅摘要 CreateImportBinding规范中的操作,第 5 步:

  1. Create an immutable indirect binding in envRec for N that references M and N2 as its target binding and record that the binding is initialized.

(我的重点)

ModuleDeclarationInstantiation 使用了该操作在处理模块的导入条目时。

所以:

b++; // Does this throw an error as well?

是的,b 是只读的。

c.prop = true; // I think mutations are always allowed, right?

只要导出的对象允许,是的。

c = {}; // but are reassignment allowed too?

不,c 是只读的。


在评论中,您说:

but when there isn't a live-binding anymore, it makes no sense to make such variables read-only

记住它们不是变量,它们是绑定(bind),这很有用。虽然变量是一种绑定(bind),但并非所有绑定(bind)都是变量(即使在 ES5 和更早版本中也是如此)。

关于它们在无关紧要时是只读的,请记住涉及两层绑定(bind):

  1. 源模块中导出的实时绑定(bind)。
  2. 消费模块中导入的实时绑定(bind)。

为了在#1 的值不会改变时使#2 可写,导入机制必须知道这一点,但该信息不在 the module's exports 中。 .导出仅给出导出绑定(bind)的名称。

此外,具有可变的导入绑定(bind)和不可变的导入绑定(bind)更难理解,也更难实现。 (从样式的 Angular 来看,重新分配导入的绑定(bind)也是令人困惑的。)

记住它们是实时绑定(bind)这一事实也很重要,这意味着导入的值可能会改变。假设:

mod1.js:

export let foo = 41;
export function incrementFoo() {
    ++foo;
};

mod2.js:

import { foo, incrementFoo } from "./mod1.js";
console.log(foo); // 41
incrementFoo();
console.log(foo); // 42 <== it changed

在这种特殊情况下,是 mod2.js 中的代码导致了更改(通过调用 incrementFoo),但不一定如此。这可能是因为 mod1.js 中发生了一些与时间相关的事件使值发生变化,或者是其他模块调用 mod1.js 的结果等.

但是因为 mod2.jsfoo 是对 mod1.jsfoo 的实时绑定(bind), mod2.js 看到了变化。

关于javascript - 导入值与其导出值断开连接是否仍然是只读的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39289463/

相关文章:

javascript - 清空用户的 HTTP_REFERER 最可靠的方法是什么?

javascript - 使用类扩展而不是 util.inherits

javascript - Webpack ES6 modules 使用索引文件时的循环依赖

javascript - 未捕获的 TypeError : (0 , _store.configureStore) 不是函数

javascript - 对单个 jQuery 对象执行多项操作的 jQuery 插件?

javascript - 如何用lodash替换数组中的十进制数

javascript - 在 vuejs 组件中添加 window.resize 事件不能独立工作

javascript - 使用类验证器中的 @MinDate 会导致 TypeError : Cannot read property 'getTime' of undefined?

javascript - Chrome 中的 ES6 模块

javascript - ES6 功能不可用