Desearía poder publicar mi proyecto palabra por palabra para esta pregunta, pero no puedo.
Esencialmente, tengo las siguientes clases:
class Lowest { someValue: string constructor(someValue: string) { this.someValue = someValue } } class Middle { lowest: Lowest constructor(someValue: string) { this.lowest = new Lowest(someValue) } } class Highest { private _middle: Middle otherValue: SomeOtherClass // normal getter public get middle(): Middle { return this._middle } public set middle(next: Middle) { this._middle = next // notice: when `_middle` is set, I update another property! otherValue.doSomething(this._middle) } constructor(config: { someValue: string }) { this.middle = new Middle(config.somevalue) } } En algunos lugares de mi programa, tengo una referencia a una instancia Highest y necesito modificar su middle.lowest.someValue . Ahora, por razones arquitectónicas que realmente no puedo describir aquí, necesito actualizar la propiedad Highest.otherValue cada vez que Highest.middle . Como estoy usando TypeScript, simplemente realizo esta operación en el setter para Highest.middle . Como tal, no puedo establecer directamente Highest.middle.lowest en algún valor.
Mi primer acercamiento fue:
const nextMiddle = Object.assign({}, highestInstance.middle) nextMiddle.lowest.someValue = "some other thing" highestInstance.middle = nextMiddle Sin embargo, esto terminó causando algunos problemas muy extraños. Ahora, no tenía una necesidad técnica real para realizar un clon profundo de nextMiddle , así que lo superé con el siguiente código:
const nextMiddle = highestInstance.middle nextMiddle.lowest.someValue = "some other thing" highestInstance.middle = nextMiddle Mientras experimentaba con la mejor solución, implementé un método Middle.copy() que básicamente solo llama a new Middle() y new Lowest() con los valores de la instancia anterior. Esto también resolvió mis problemas técnicos, pero me dejó aún más confundido.
Entiendo que hay una gran diferencia entre simplemente reasignar el highestInstance.middle y usar Object.assign() para clonarlo, pero no entiendo por qué no parece haber una diferencia entre Object.assign() y new Middle() . new Middle()
¿Cuáles son las diferencias reales con estos tres métodos de clonación/reasignación?
no tenía una necesidad técnica real para realizar un clon profundo de nextMiddle, así que lo superé con el siguiente código:
Object.assign({}, highestInstance.middle) está creando una copia superficial y no una copia profunda.
El problema aquí es que usar Middle Setter te obliga a realizar otherValue: SomeOtherClass solo cuando se actualiza middle .
lo actualizará incluso si solo haces:
high.middle.lowest.someValue = 'new value' high.middle = high.middle; // setter triggeredUna posible solución es crear una cadena de devolución de llamada en lugar de usar un setter:
type voidFun = () => void; class Lowest { private _someValue: string public get someValue(): string { return this._someValue } private update?: voidFun; // create an optional callback public set someValue(next: string) { this._someValue = next this.update?.call(undefined); } constructor(someValue: string, fun?: voidFun) { this._someValue = someValue this.update = fun;// pass down } } class Middle { lowest: Lowest; constructor(someValue: string, fun?: voidFun) { this.lowest = new Lowest(someValue, fun) } } class Highest { private _middle: Middle otherValue: any = {}; // normal getter public get middle(): Middle { return this._middle } // now you dont need middle setting so it cant be updated by anyone directly // if you still want to have you can have it too private callBack = () => { console.log('lower was update'); this.otherValue.myMiddle = this._middle.lowest.someValue; } constructor(config: { someValue: string } = { someValue : 'constr' }) { this._middle = new Middle(config.someValue, this.callBack) } } let high = new Highest() high.middle.lowest.someValue = 'new value' // high.middle = high.middle; // now not possible unless you create setter console.log('updated middle high',high)