У меня есть следующий код, написанный в ES6 плюс некоторые предложения по Stage 3:
class Parent {
constructor(x){
this.x = x;
this.otherProperty = "preserve across copy";
}
printX=()=>{
console.log(this.x);
}
squareX=()=>{
this.x = this.x *this.x;
}
}
class Child extends Parent {
constructor(x){
super(x);
}
}
const c = new Child(20);
const copy = {...c, x: 10};
console.log(JSON.stringify(c));
c.squareX();
console.log(JSON.stringify(c));
console.log(JSON.stringify(copy));
copy.squareX();
console.log(JSON.stringify(copy));
Демо-версия: https://jsbin.com/wuqenabaya/1/edit?js,console
Идея состоит в том, чтобы создать копию экземпляра c
при обновлении некоторых его свойств. Результат этого кода:
{x: 20, otherProperty: "preserve across copy"}
{x: 400, otherProperty: "preserve across copy"}
{x: 10, otherProperty: "preserve across copy"}
{x: 10, otherProperty: "preserve across copy"}
Так как вы можете видеть, что copy.squareX()
не обновляет экземпляр copy
. Проблема в том, что функция squareX()
все еще привязана к старому экземпляру c
.
Я хочу, чтобы последний вызов squareX()
экземпляр copy
. Как это можно достичь?
EDIT: Я использую Babel со следующими плагинами, чтобы использовать новые функции JS (распространение, реквизит функций).
{
"presets": [
["es2015", { "modules": false }],
"stage-0",
"react"
],
"plugins": [
"react-hot-loader/babel",
"transform-object-rest-spread",
"transform-class-properties",
"transform-flow-strip-types"
]
}
Есть несколько проблем с попыткой использовать свойства распространения для этого, не в последнюю очередь, что вы получите объект, прототипом которого является Object.prototype
, а не Child.prototype
.
Вы также используете синтаксис полей для методов, который делает эти поля собственными свойствами объекта, а не свойствами прототипа, которые, по-видимому, не имеют никакой причины в этом случае; просто используйте метод синтаксис.
Чтобы сделать копию, дайте себе ветку "конструктор копирования" в вашем конструкторе:
constructor(x, ...more){
if (x instanceof Child) {
// The copy constructor branch
super(x.x);
Object.assign(this, x, ...more);
} else {
super(x);
}
}
Или, если хотите, просто сделайте это, когда вы создадите copy
:
const copy = Object.assign(new Child(c.x), c, {x: 10});
В любом случае, если вы предпочитаете использовать поля, а не методы, вам придется корректировать их, поскольку в противном случае вы будете копировать squareX
и printX
.
Живой пример с использованием методов и конструктор копирования:
class Parent {
constructor(x){
this.x = x;
this.otherProperty = "preserve across copy";
}
printX() {
console.log(this.x);
}
squareX() {
this.x = this.x *this.x;
}
}
class Child extends Parent {
constructor(x, ...more){
if (x instanceof Child) {
super(x.x);
Object.assign(this, x, ...more);
} else {
super(x);
}
}
}
const c = new Child(20);
const copy = new Child(c, {x: 10});
console.log(JSON.stringify(c));
c.squareX();
console.log(JSON.stringify(c));
console.log(JSON.stringify(copy));
copy.squareX();
console.log(JSON.stringify(copy));