Javascript 试图理解ES6中的Object.assign行为

Javascript 试图理解ES6中的Object.assign行为,javascript,ecmascript-6,Javascript,Ecmascript 6,我试图理解我在ES6课程中观察到的这种行为。考虑下面的代码。它非常简单:我有一个父类(parent)和一个子类(child)继承自它Parent类有一个名为getLabel的方法,该方法只返回该类的label属性 当我创建一个子类的实例时,设置它的标签并尝试打印它,这一切都很好 但是,当我在第一个实例上使用Object.assign创建子类的另一个实例时,新实例保留第一个实例的标签值,即使我正在显式更改它 class Parent { constructor(label) { thi

我试图理解我在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".
我不知道为什么会这样

然后我所做的改变了我在
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对上述代码的处理:。

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

然后,当您使用
Object.assign
时,
c1
接收
c
的方法,该
值将是
c
,即使您在
c1
上调用它也是如此。所以你得到了
c.label
,它仍然是
的“孩子”

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

类父类{
建造师(标签){
this.label=标签;
}
getLabel(){
返回此.label;
}
}
类子级扩展父级{
建造师(标签){
超级(标签);
this.label=标签;
}
}
常数c=新的子项(“子项”);
console.log('c getLabel()='+c.getLabel());//“孩子”
const c1=Object.assign(新的子对象('c1'),c);
c1.标签=‘子修改’;

console.log('c1 getLabel()='+c1.getLabel());//“Child-Modified”
箭头函数使用词法
。您的对象有一个名为
getLabel
的属性,当您调用
对象时,该属性会被复制到新的子对象。assign
,该属性包含一个函数,该函数具有对原始父对象的词法
引用。如果您使用普通函数而不是箭头函数,您将不会看到这种行为。顺便说一下,
super(label)
已经分配了
this.label
,因此您不需要
this.label=label
@Oriol…谢谢!这是我今天看到的第二个问题,问题是由于使用了箭头函数。我想人们是爱上了它的简单语法,而没有意识到它在行为上有这么大的不同。它对回调函数很好,但对对象方法却不好。@Barmar:这就是我创建它的原因,但它仍然是特定的(例如,它不适合这个用例)。就我个人而言,我希望能够把每一个误用arrow函数的问题都当作一个问题的重复来解决,但这可能只是一厢情愿。