问题描述
我通常按以下几行实现继承。
I typically implement inheritance along the following lines.
function Animal () { this.x = 0; this.y = 0;}
Animal.prototype.locate = function() {
console.log(this.x, this.y);
return this;
};
Animal.prototype.move = function(x, y) {
this.x = this.x + x;
this.y = this.y + y;
return this;
}
function Duck () {
Animal.call(this);
}
Duck.prototype = new Animal();
Duck.prototype.constructor = Duck;
Duck.prototype.speak = function () {
console.log("quack");
return this;
}
var daffy = new Duck();
daffy.move(6, 7).locate().speak();
我读过如果我理解正确,我可以使用 Object.create
和 Object.assign
而不是?它真的那么简单吗?
I've read this post by Eric Elliott and if I understand correctly I can use Object.create
and Object.assign
instead? Is it really that simple?
var animal = {
x : 0,
y : 0,
locate : function () {
console.log(this.x, this.y);
return this;
},
move : function (x, y) {
this.x = this.x + x;
this.y = this.y + y;
return this;
}
}
var duck = function () {
return Object.assign(Object.create(animal), {
speak : function () {
console.log("quack");
return this;
}
});
}
var daffy = duck();
daffy.move(6, 7).locate().speak();
顺便说一句,按照惯例,构造函数是大写的,如果作为构造函数的对象文字也是大写的?
As an aside, by convention constructor functions are capitalized, should object literals that act as constructors also be capitalized?
我发现这里有很多问题讨论 new
与 Object.create
,但它们通常似乎与 Duck.prototype = new Animal();
相对于 Duck.prototype = Object.create( Animal.prototype);
I realise there are many questions here discussing new
versus Object.create
, but they typically seem to relate to Duck.prototype = new Animal();
versus Duck.prototype = Object.create(Animal.prototype);
推荐答案
是的,就这么简单。在使用 Object.create / Object.assign
的示例中,您正在使用工厂函数来创建 duck
的新实例(类似于jQuery创建新实例的方式,如果你选择一个元素 var body = $('body')
)。这种代码风格的一个优点是,当你想要创建一个新的 duck时,它不会强迫你调用
实例(与ES2015类相对)。 animal
的构造函数
Yes, it is that simple. In your example with Object.create/Object.assign
, you are using a factory function to create new instances of duck
(similar to the way jQuery creates new instances if you select an element with var body = $('body')
). An advantage of this code style is, that it doesn't force you to call a constructor of animal
when you want to create a new duck
instance (as opposed to ES2015 Classes).
初始化差异
也许一个有趣的小问题与你使用构造函数(或任何其他初始化函数)的工作方式略有不同:
Maybe one interesting tidbit that works slightly differently than if you were to use a constructor (or any other initialization function):
创建<$ c时$ c> duck instace, animal
的所有属性都在 [[Prototype]] $ c $中c>
duck
实例的插槽。
When you create a duck
instace, all the properties of animal
are in the [[Prototype]]
slot of the duck
instance.
var daffy = duck();
console.log(daffy); // Object { speak: function() }
所以 daffy
还没有任何自己的 x
和 y
属性。但是,当您拨打以下电话时,会添加以下内容:
So daffy
does not have any own x
and y
properties yet. However, when you call the following, they will be added:
daffy.move(6, 7);
console.log(daffy); // Object { speak: function(), x: 6, y: 7 }
为什么?在 animal.move
的函数体中,我们有以下语句:
Why? In the function-body of animal.move
, we have the following statement:
this.x = this.x + x;
所以当你用 daffy.move
,此
指的是 daffy
。因此它会尝试将 this.x + x
分配给 this.x
。由于 this.x
尚未定义, [[原型]]
链 daffy
遍历到 animal
,其中定义了 animal.x
。
So when you call this with daffy.move
, this
refers to daffy
. So it will try to assign this.x + x
to this.x
. Since this.x
is not yet defined, the [[Prototype]]
chain of daffy
is traversed down to animal
, where animal.x
is defined.
因此,在第一次调用中,赋值右侧的 this.x
指的是动物.x
,因为未定义 daffy.x
。第二次调用 daffy.move(1,2)
,右侧的 this.x
将 daffy.x
。
Thus in the first call, the this.x
on the right side of the assignment refers to animal.x
, because daffy.x
is not defined. The second time daffy.move(1,2)
is called, this.x
on the right side will be daffy.x
.
替代语法
或者,您也可以使用 Object.setPrototypeOf
而不是 Object.create / Object.assign
( ):
Alternatively, you could also use Object.setPrototypeOf
instead of Object.create/Object.assign
(OLOO Style):
var duck = function () {
var duckObject = {
speak : function () {
console.log("quack");
return this;
}
};
return Object.setPrototypeOf(duckObject, animal);
}
命名约定
我不知道任何既定的惯例。 Kyle Simpson在OLOO中使用大写字母,Eric Elliot似乎使用小写字母。我个人会坚持使用小写,因为充当构造函数的对象文字已经是完全成熟的对象本身(不仅仅是蓝图,就像类一样)。
I'm not aware of any established conventions. Kyle Simpson uses uppercase letters in OLOO, Eric Elliot seems to use lowercase. Personally I would stick with lower-case, because the object literals that act as constructors are already fully fledged objects themselves (not just blueprint, like classes would be).
Singleton
如果您只想要一个实例(例如单个实例),您可以直接调用它:
If you only wanted a single instance (e.g. for a singleton), you could just call it directly:
var duck = Object.assign(Object.create(animal), {
speak : function () {
console.log("quack");
return this;
}
});
duck.move(6, 7).locate().speak();
这篇关于使用Object.assign和Object.create进行继承的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!