导出的变量是只读的吗?

时间:2018-12-04 16:57:56

标签: typescript

globals.ts:

export let TimeZone: number = 0;

app.js

import * as globals from "./globals";
globals.TimeZone = -5;

最后一行给出:

  

错误TS2540:因为它是一个只读属性,所以无法分配给“ TimeZone”。

为什么?

1 个答案:

答案 0 :(得分:5)

导入是源模块环境中导出的绑定的只读视图。即使源绑定是可变的(如您的示例中所示),也不能使用导入的视图对其进行修改。只有导出它的模块可以修改它。

为什么?因为导入变量的一个模块不应该到达源模块并更改变量的值。如果源模块希望使使用它的模块能够更改导出变量的值,则可以公开一个函数来执行此操作。 (或公开具有可变属性的对象。)

请记住,模块在导入模块的各个模块之间共享。因此,如果模块A和B都导入模块C,则您不希望模块A修改模块B看到的内容(即使模块C可以,因为它是变量,而不是常量)。

FWIW,这是一个示例(live copy on plunker):

index.html

<!DOCTYPE html>
<html>

  <head>
  </head>

  <body>
    <p id="display">0</p>
    <script type="module" src="imp1.js"></script>
    <script type="module" src="imp2.js"></script>
  </body>

</html>

counter.js

export let counter = 0;

export function increment() {
  ++counter;
}

imp1.js

import { counter } from "./counter.js";

const display = document.getElementById("display");

setInterval(() => {
  // This module sees changes counter.js makes to the counter
  display.textContent = counter;
}, 100);

imp2.js

import { counter, increment } from "./counter.js";

// Trying to set it directly fails
try {
  counter = 127;
} catch (e) {
  document.body.insertAdjacentHTML(
    "beforeend",
    "imp2: Failed to directly set counter to 127"
  );
}

setInterval(() => {
  // But it can ask counter.js to do it
  increment();
}, 200);
相关问题