gpt4 book ai didi

javascript - 当使用 Javascript 的 Reflect API 构建一个扩展另一个类的实例时,为什么索引数组是共享作用域?

转载 作者:行者123 更新时间:2023-12-02 23:08:42 25 4
gpt4 key购买 nike

我使用 Typescript playground 构建了一个示例,但该行为与 typescript 无关。在代码中显示更容易一些(链接包括编译的 JS,对于那些希望忽略 TS 的人):

如果您扩展一个使用索引数组作为属性的类

class BaseClass {
_meta: {[key: string]: string};
constructor() {
this._meta = {};
}
}

class MyClass extends BaseClass {
prop1?: string;

constructor(init: Partial<MyClass>){
super()
Object.assign(this, init);
}
}

然后从基本模型使用反射 API 创建其他实例,您可以获得不同的行为,具体取决于您构建后续模型的方式。

如果您创建一个新对象来分配给 _meta,它会按照您期望的方式工作:

const baseInstance = new MyClass({
prop1: 'base',
_meta: {
hello: 'world'
}
})

const reflectInstance = Reflect.construct(MyClass, [baseInstance]);
reflectInstance._meta = { hello: 'reflection' }

alert("1 " + JSON.stringify(baseInstance)) // as expected
alert("2 " + JSON.stringify(reflectInstance)) // as expected

但是如果您使用数组表示法分配给容器,则范围会受到污染,即它与源模型共享范围:

const contaminatedInstance = new MyClass({
prop1: 'contaminated',
_meta: {
goodbye: 'world'
}
})

const bogusInstance = Reflect.construct(MyClass, [contaminatedInstance]);
bogusInstance._meta['goodbye'] = 'contaminated';

alert("3 " + JSON.stringify(contaminatedInstance)) // _meta has unexpectedly changed
alert("4 " + JSON.stringify(bogusInstance)) // as a result of bogusInstance

有谁知道这是为什么吗?我可以通过说 _meta 属性有一个公共(public)地址来模糊地证明事情的合理性,并且因为它是扩展的,所以没有对基本模型的 new 调用,从而使其变得通用;但当它出现在单元测试之外时,这是一个很难记住的情况;尤其是在公关期间。

关于如何在仍然使用数组表示法的同时避免这种情况的任何建议都会很棒。

谢谢!

最佳答案

这与反射无关。您将得到相同的行为:

  new MyClass(new MyClass({ shared: "false", _meta: { shared: "true" } })

只是Object.assign shallow copies ,因此两个实例的 _meta 属性将包含 reference to the same object. .

一些伪内存结构使这一点更加清晰:

  #1 { // MyClass
[[Construct]]: Code,
prototype: #2
}

#2 { // MyClass.prototype
constructor: #1,
// yet empty
}

#3 { shared: "true" } // the _meta object, created inside the object passed to the first instance constructor

#4 { // the object passed to the first instance constructor
shared: "false",
_meta: #3,
}

#5 { // the first MyClass instance
[[prototype]]: #2,
shared: "false", // shallow copied from #4
_meta: #3
}

#6 { // the second MyClass instance
[[prototype]]: 2,
shared: "false", // shallow copied from #5
_meta: #3, // same reference as #4._meta
}

关于javascript - 当使用 Javascript 的 Reflect API 构建一个扩展另一个类的实例时,为什么索引数组是共享作用域?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57467502/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com