Javascript 如何将克隆的函数分配给此新实例

Javascript 如何将克隆的函数分配给此新实例,javascript,es6-class,Javascript,Es6 Class,我有以下用ES6编写的代码,以及一些第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 exten

我有以下用ES6编写的代码,以及一些第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));
现场演示:

其思想是在更新实例的某些属性时创建实例
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
。如何做到这一点

编辑:我正在使用Babel和以下插件,以允许使用新的JS功能(传播、功能道具)


尝试为此使用扩展属性时会出现一些问题,尤其是您最终会得到一个原型为
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);
  }
}  
或者,如果您愿意,只需在创建
复制
的位置执行即可:

const copy = Object.assign(new Child(c.x), c, {x: 10});
在这两种情况下,如果您选择继续使用字段而不是方法,则必须进行调整,否则您将同时复制
squareX
printX

使用方法和复制构造函数的实时示例:

constructor(x, ...more){
  if (x instanceof Child) {
    // The copy constructor branch
    super(x.x);
    Object.assign(this, x, ...more);
  } else {
    super(x);
  }
}  
类父类{
构造器(x){
这个.x=x;
this.otherProperty=“跨副本保留”;
}
printX(){
console.log(this.x);
}
平方(){
this.x=this.x*this.x;
}
}
类子级扩展父级{
构造函数(x,…更多){
if(子对象的x实例){
超级(x.x);
赋值(这个,x,…更多);
}否则{
超级(x);
}
}  
}
常数c=新生儿(20);
const copy=新的子级(c,{x:10});
log(JSON.stringify(c));
c、 平方();
log(JSON.stringify(c));
log(JSON.stringify(copy));
copy.squareX();

log(JSON.stringify(copy))注意:“ES6”(ES2015)没有排列属性。事实上,他们甚至不在ES2017。他们可能在ES2018;当前是。它是更新类的选项吗?我想到的是一个静态工厂函数,它作为参数接受一个类实例,读取所需的属性,生成一个新实例,更新这些属性,然后返回新实例。与通过object Literal克隆旧实例不同,您正在使用的也不在任何规范中,而且也处于第3阶段。@T.J.Crowder:我实际上在使用Babel。我更新了答案以反映这一事实。好吧-代码将完全与
函数
表达式一起工作。