【问题标题】:Exported variables are read only?导出的变量是只读的?
【发布时间】:2018-12-04 16:57:56
【问题描述】:

globals.ts:

export let TimeZone: number = 0;

app.js

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

最后一行给出:

错误 TS2540:无法分配给“时区”,因为它是只读属性。

为什么?

【问题讨论】:

标签: typescript


【解决方案1】:

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

为什么?因为一个导入变量的模块不应该能够进入源模块并改变变量的值。如果源模块想让模块使用它来更改导出变量的值,它可以公开一个函数来做到这一点。 (或者公开一个具有可变属性的对象。)

请记住,模块在导入它们的各个模块之间共享。因此,如果模块 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);

我应该注意,虽然您不能修改绑定(在您的示例中为TimeZone),但如果您导出对象,则可以修改该对象的状态。例如:

// In the exporting module
export const container = {
    TimeZone: 0,
};

// In the importing module
import { container } from "./module.js";
container.TimeZone = 42;

这行得通,并且任何同时导入container 的代码都可以看到更改。有时您想防御这种情况,您可以使用Object.freeze(如果源模块不需要更改对象的属性)或Proxy

但同样,更改对象的状态与更改导出的绑定的值不同。

【讨论】:

  • commonjs 让我们
  • @java-addict301 - 我不这么认为,你能给我举个例子吗?您可能会误认为修改对象的状态(在 CommonJS 和 ESM 中都可以这样做)与修改导出的变量(我认为您不能这样做)。 (这很像函数参数:在函数中,您可以为参数分配一个新值,但这对传入的参数没有影响;但是您可以更改一个参数的 state传入的对象,并且该更改在调用站点上也可见。)CommonJS 和 ESM 当然存在差异,但我不认为这是其中之一...?
猜你喜欢
  • 1970-01-01
  • 2020-08-07
  • 2015-08-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-01-23
相关资源
最近更新 更多