javascript - TypeScript 中的不可变数据

标签 javascript variables angular typescript immutability

情节:

我有一个名为myVar的 protected 变量,它的结构和数据由构造函数定义,例如

this.myVar = this.legacy ? this.legacy.listing : this.default;

当您编辑myVar时,它也会更改this.default结构和数据。所以我的问题很简单:如何保持 this.default 不可变?

感谢任何帮助,

PS:诸如此类的函数

private default = (): Structure[] => {
  return [{
    param1: 'param1'
  }]
}

这不是我的目标。

最佳答案

tl;dr:您需要使 myVar 和您的默认结构成为不同的对象。 readonly 不是解决方案。

readonly 不是解决方案

readonly 对您尝试执行的操作没有帮助。如果您在 numberstring 等基本类型上使用 readonly,则该字段实际上是不可变的。但是,保存 Object(及其派生类,如 FunctionArray)的字段包含对目的。 readonly 使引用不可变,而不是对象本身。这与const 完全相同。这是一个使用 const 的示例:

class Structure {
    public prop: number = 1;
}

const a: Structure = new Structure();
console.log(a.prop);
a.prop++; // It does not matter that `a` was marked `const`.
console.log(a.prop);

上面的代码将显示:

1
2

我们已经能够改变a,即使它是只读的。

现在,这是一个 readonly 的示例:

class Structure {
    public prop: number = 1;
}

class Something {
    // This is the analogue to `default` in your question. I don't like
    // the name default because it is a keyword and looks funky here in 
    // syntax highlighting.
    private static readonly defaultStructure = new Structure();

    readonly myVar: Structure;

    constructor() {
        this.myVar = Something.defaultStructure;
    }

    doSomething() {
        this.myVar.prop++;
    }

    // `readonly defaultStructure` prevents this:
    // evil() {
    //     Something.defaultStructure = new Structure();
    // }
}

const something = new Something();
console.log(something.myVar);
something.doSomething();
const somethingElse = new Something();
console.log(somethingElse.myVar);

这显示:

Structure { prop: 1 }
Structure { prop: 2 }

我们已将 myVardefaultStructure 设为只读,但修改 myVar 会修改 defaultStructure

反对:“但是,Louis,你这个大笨蛋,你应该将 prop 设置为只读!”

不,如果我设置 prop readonly 那么我就不能再修改 myVar 了,但我希望能够修改 myVar!

好的,现在怎么办?

最终,无论使用多少 readonly 或装饰器或 Object.freeze 都无法满足您的需求。只要 myVardefaultStructure 都引用同一个对象,您就可以 a) 通过 myVar 改变 defaultStructure code>,或 b) 如果您使 defaultStructure 指向的对象不可变,您也会使 myVar 指向的对象不可变,因为它们是相同的对象。您需要使 myVar 和您的默认结构是不同的对象。

为此,您有几种选择:

  1. 您可以重新构造myVar,而不是从默认值进行分配。您在问题中展示了一个这样的示例,并表示您没有瞄准或那样的目标,但这是一个有效的选项。

  2. 您可以将默认结构的克隆分配给myVar。克隆对象的方法有很多种。一般情况下,需要深拷贝。有许多用于深度复制的库。您应该研究什么最适合您的具体情况。

在这种情况下,在这两种情况下,我更喜欢选项 1,因为我知道默认结构必须包含什么。当我必须获取可以具有多个不同值的结构的副本时,我会使用克隆。

关于javascript - TypeScript 中的不可变数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39762871/

相关文章:

javascript - 从一个 div 过渡到另一个 div

PHP变量和查询

c#引用变量内存分配

Angular Material 图标 mat-icon 未正确显示

javascript - 是否可以压缩代码以允许多个变量而不是每个变量一行?

javascript - 如果文本框中有内容,则文本验证不起作用

javascript - 服务器发送事件有哪些好的用例

php - 双引号中的echo变量在IDE中显示语法错误

javascript - Angular2使用 typescript 环境分离文件

Angular 4 - 未调用 canActivate observable