Как назначить клонированные функции новому этому экземпляру

1

У меня есть следующий код, написанный в 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"
  ]
}
  • 1
    Примечание. «ES6» (ES2015) не имеет свойств распространения. На самом деле, они даже не в ES2017. Они могут быть в ES2018; в настоящее время предложение 3 этапа .
  • 0
    это опция для обновления классов? Я имею в виду нечто вроде статической фабричной функции, которая в качестве аргумента принимает экземпляр класса, считывает необходимые свойства, генерирует новый экземпляр, обновляет эти свойства и возвращает новый экземпляр. вместо клонирования старого экземпляра через литерал объекта
Показать ещё 3 комментария
Теги:
es6-class

1 ответ

2
Лучший ответ

Есть несколько проблем с попыткой использовать свойства распространения для этого, не в последнюю очередь, что вы получите объект, прототипом которого является 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));

Ещё вопросы

Сообщество Overcoder
Наверх
Меню