试图了解ES6中的Object.assign行为
问题描述:
我试图理解这种行为,我正在观察ES6类。考虑下面的代码。这很简单:我有一个父类(Parent
)和一个子类(Child
)从它继承。 Parent
类有一个名为getLabel
的方法,它简单地返回该类的标签属性。试图了解ES6中的Object.assign行为
当我创建子类的实例时,设置它的标签并尝试打印它的所有作品。
但是,当我在第一个实例上使用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
是在每个实例中定义的,所以它不在原型中共享。由于您使用箭头函数定义它,因此它不会为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"
箭头函数使用词法'this'。你的对象有一个名为'getLabel'的属性,当你调用Object.assign时,该属性被复制到你的新子中,该属性包含一个函数,该函数对原始Parent有一个词汇'this'引用。如果您使用普通函数而不是箭头函数,则不会看到该行为。 – Paulpro
顺便说一句,'super(label)'已经指定'this.label',所以你不需要'this.label = label'。 – Oriol
@Oriol ...谢谢!这只是我想为这个问题提出一个例子。 –