我试图了解我在ES6类中观察到的这种行为。考虑下面的代码。这很简单:我有一个父类(Parent)和一个子类(Child)继承。 Parent类具有一个称为getLabel的方法,该方法仅返回该类的label属性。

当我创建子类的实例时,设置其标签并尝试将其正常打印。

但是,当我在第一个实例上使用Object.assign创建子类的另一个实例时,即使我显式更改了新实例,该新实例仍保留了第一个实例的标签值。

class Parent {
  constructor(label) {
    this.getLabel = () => {
      return this.label;
    };
    this.label = label;
  }
}

class Child extends Parent {
  constructor(label) {
    super(label);
    this.label = label;
  }
}

const c = new Child('Child');
console.log('c getLabel() = ' + c.getLabel());//Prints "Child"
const c1 = Object.assign(new Child('C1'), c);
c1.label = 'Child Modified';
console.log('c1 getLabel() = ' + c1.getLabel());//Prints "Child" again instead of "Child Modified".

我不确定为什么会这样!

然后,我所做的更改更改了我在getLabel类中定义Parent方法的方式:
class Parent2 {
  constructor(label) {
    this.label = label;
  }

  getLabel() {
    return this.label;
  }
}

class Child2 extends Parent2 {
  constructor(label) {
    super(label);
    this.label = label;
  }
}

const c2 = new Child2('Child 2');
console.log('c2 getLabel() = ' + c2.getLabel());//Prints "Child 2" as expected.
const c3 = Object.assign(new Child2('C3'), c2);
c3.label = 'Child 2 Modified';
console.log('c3 getLabel() = ' + c3.getLabel());//Prints "Child 2 Modified" as expected.

如果有人可以解释这两种不同的行为,我将不胜感激。

这是上面代码的ES6小提琴:http://www.es6fiddle.net/is6ex359/

最佳答案

这是因为getLabel是在每个实例中定义的,因此不在原型(prototype)中共享。并且由于您使用箭头函数定义了它,所以它没有为this定义本地绑定(bind),因此this值将是constructor之一。

然后,当您使用Object.assign时,c1接受c的方法,即使您在this上调用c,其c1值也将是c.label。这样您会得到'Child',仍然是Object.assign

因此,应避免使用箭头功能。我建议在原型(prototype)中定义方法:

class Parent {
  constructor(label) {
    this.label = label;
  }
  getLabel() {
    return this.label;
  }
}
class Child extends Parent {
  constructor(label) {
    super(label);
    this.label = label;
  }
}
const c = new Child('Child');
console.log('c getLabel() = ' + c.getLabel()); // "Child"
const c1 = Object.assign(new Child('C1'), c);
c1.label = 'Child Modified';
console.log('c1 getLabel() = ' + c1.getLabel()); // "Child Modified"


(注意getLabel不会分配c1.getLabel ==== c.getLabel,因为它是继承的,但无论如何还是ojit_code)

或在构造函数中,但使用函数表达式:

class Parent {
  constructor(label) {
    this.getLabel = function() {
      return this.label;
    };
    this.label = label;
  }
}
class Child extends Parent {
  constructor(label) {
    super(label);
    this.label = label;
  }
}
const c = new Child('Child');
console.log('c getLabel() = ' + c.getLabel()); // "Child"
const c1 = Object.assign(new Child('C1'), c);
c1.label = 'Child Modified';
console.log('c1 getLabel() = ' + c1.getLabel()); // "Child Modified"

10-08 02:12