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

时间:2016-09-02 09:50:52

标签: 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),则会从此导出值中断开相应的导入。考虑到这一点,这样的导入仍然是只读的,我可以重新分配a还是c

1 个答案:

答案 0 :(得分:5)

导入绑定始终是只读的,请参阅规范中的抽​​象CreateImportBinding操作,步骤5:

  
      
  1. envRec 中为 N 创建不可变间接绑定,引用 M N2 作为其目标绑定并记录绑定已初始化。
  2.   

(我的重点)

在处理模块的导入条目时,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是只读的。

在评论中,你说过:

  

但是当没有活动绑定时,将这些变量设为只读是没有意义的

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

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

  1. export 在源模块中的实时绑定。
  2. 消耗模块中 import 的实时绑定。
  3. 为了在#1的值不会改变时使#2可写,导入机制必须知道,但该信息不在the module's exports中。导出只是给出导出绑定的名称。

    此外,具有可变的导入绑定以及不可变的导入绑定更难以理解并且实现起来更复杂。 (从样式的角度来看,重新分配导入的绑定也会让人感到困惑。)