试图理解对象.在ES6中分配行为

Trying to understand Object.assign behavior in ES6

本文关键字:分配 ES6 对象      更新时间:2023-09-26

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

当我创建一个子类的实例时,设置它的标签并尝试打印它都工作得很好。

然而,当我通过在第一个实例上使用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".

我不知道为什么会发生这种情况!

我所做的改变了我在Parent类中定义getLabel方法的方式:

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 Fiddle: http://www.es6fiddle.net/is6ex359/.

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

那么,当您使用Object.assign时,c1接收c的方法,并且this的值将是c,即使您在c1上调用它。所以你得到c.label,它仍然是'Child'

所以你应该避免箭头函数。我建议在原型中定义方法:

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"

(注意Object.assign没有分配getLabel,因为它是继承的,但c1.getLabel ==== c.getLabel无论如何)

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

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"