使用`Object.create`进行继承的好处 [英] Benefits of using `Object.create` for inheritance

查看:172
本文介绍了使用`Object.create`进行继承的好处的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直试图围绕ECMAScript 5中引入的新 Object.create 方法。

I've been trying to wrap my head around the new Object.create method which was introduced in ECMAScript 5.

通常当我想使用继承时,我会这样做:

Usually when I want to use inheritance I do something like this:

var Animal = function(name) { this.name = name; }
Animal.prototype.print = function() { console.log(this.name); }

var Dog = function() 
{ 
  return Animal.call(this, 'Dog'); 
}

Dog.prototype = new Animal();
Dog.prototype.bark = function() { console.log('bark'); }

我只是将一个新创建的Animal对象分配给Dog的原型,一切都像魅力一样:

I just assign a newly created Animal object to Dog's prototype and everything works like a charm:

var dog1 = new Dog();
dog1.print(); // prints 'Dog'
dog1.bark(); // prints 'bark'
dog1.name; //prints 'Dog'

但是人们(没有解释)说 Dog.prototype = new Animal(); 不是继承的工作方式,我应该使用Object.create方法:

but people(without explaining) are saying that Dog.prototype = new Animal(); is not the way inheritance works and that I should use Object.create approach:

Dog.prototype = Object.create(Animal.prototype);

这也有效。

使用 Object.create 有什么好处,还是我错过了什么?

What's the benefit of using Object.create or am I missing something?

更新:有人说 Dog.prototype = Animal.prototype; 也可以。所以现在我完全糊涂了

UPDATE: Some say that Dog.prototype = Animal.prototype; can also work. So now I'm totally confused

推荐答案

在下面我假设你只对<$ c感兴趣$ c> Object.create 更适合设置继承。

In the following I assume you are only interested in why Object.create is preferable for setting up inheritance.

为了理解这些好处,首先要弄清楚什么是类在JavaScript中。您有两部分:

To understand the benefits, lets first clarify what a "class" is made of in JavaScript. You have two parts:


  1. 构造函数函数。此函数包含创建类实例的所有逻辑,即实例特定代码。

  1. The constructor function. This function contains all the logic to create an instance of the "class", i.e. instance specific code.

原型对象。这是实例继承的对象。它包含应在所有实例之间共享的所有方法(和其他属性)。

The prototype object. This is the object the instance inherits from. It contains all methods (and other properties) that should be shared among all instances.

继承建立 is-a 关系,例如, 动物。这是如何用构造函数和原型对象表达的?

Inheritance establishes an is-a relation, for example, a Dog is an Animal. How is this expressed in terms of constructor function and prototype object?

显然,狗必须拥有与动物相同的方法,即 Dog 原型 object必须以某种方式合并 Animal prototype 对象中的方法。有多种方法可以做到这一点。你经常会看到这个:

Obviously a dog must have the same methods as an animal, that is the Dog prototype object must somehow incorporate the methods from the Animal prototype object. There are multiple ways to do this. You will often see this:

Dog.prototype = new Animal();

这是因为 Animal instance 继承自 Animal prototype 对象。 它还暗示每只狗都继承自一个特定的 Animal 实例。这似乎有点奇怪。实例特定代码不应仅在构造函数函数中运行吗?突然,实例特定代码和原型方法似乎是混合的。

This works because an Animal instance inherits from the Animal prototype object. But it also implies that every dog inherits from one specific Animal instance. That seems to be a bit strange. Shouldn't instance specific code only be run in the constructor function? Suddenly instance specific code and prototype methods seem to be mixed.

我们实际上并不想运行<当前code> Animal 实例特定代码,我们只想要 Animal <中的所有方法em> prototype 对象。这就是 Object.create 允许我们这样做:

We don't actually want to run Animal instance specific code at that moment, we only want all the methods from the Animal prototype object. That is what Object.create lets us do:

Dog.prototype = Object.create(Animal.prototype);

这里我们创建一个新的动物实例,我们只获取原型方法。 实例特定代码在构造函数内完全执行:

Here we are not creating a new Animal instance, we only get the prototype methods. The instance specific code is executed exactly where it should be, inside the constructor:

function Dog() { 
   Animal.call(this, 'Dog'); 
}

最大的优势是 Object.create 始终工作。使用 new Animal()仅在构造函数不期望任何参数时才有效。想象一下,如果构造函数看起来像这样:

The biggest advantage is that Object.create will always work. Using new Animal() only works if the constructor does not expect any arguments. Imagine if the constructor looked like this:

function Animal(name) { 
    this.name = name.toLowerCase();
}

您必须将字符串传递给 Animal ,否则你会收到错误。你做什么 Dog.prototype = new Animal(??); ?你通过哪个字符串实际上并不重要,只要传递某事,这有希望告诉你这是一个糟糕的设计。

You always have to pass a string to Animal, otherwise you will get an error. What will you pass when you do Dog.prototype = new Animal(??);? It doesn't actually matter which string you pass, as long as pass something, which hopefully shows you that this is bad design.


有人说 Dog.prototype = Animal.prototype; 也可以。所以现在我完全糊涂了

Some say that Dog.prototype = Animal.prototype; can also work. So now I'm totally confused

所有添加来自 Animal.prototype Dog.prototype 将正常。但解决方案的质量不同。在这种情况下,您将遇到的问题是,您添加到 Dog.prototype 的任何方法也将添加到 Animal.prototype

Everything that "adds" the properties from Animal.prototype to Dog.prototype will "work". But the solutions are of different quality. In this case here you will have the problem that any method you add to Dog.prototype will also be added to Animal.prototype.

示例:

Dog.prototype.bark = function() {
    alert('bark');
};

由于 Dog.prototype === Animal.prototype ,所有 Animal 实例现在都有一个方法 bark ,这肯定不是你想要的。

Since Dog.prototype === Animal.prototype, all Animal instances have a method bark now, which is certainly not what you want.

Object.create (甚至新动物)通过创建一个继承自 Animal.prototype 的新对象,为继承添加一级间接,并且新对象变为 Dog.prototype

Object.create (and even new Animal) add one level of indirection to the inheritance by creating a new object which inherits from Animal.prototype and that new object becomes Dog.prototype.

ES6中的继承

ES6引入了一种新语法来创建构造函数和原型方法,如下所示:

ES6 introduces a new syntax to create constructor functions and prototype methods, which looks like this:

class Dog extends Animal {

  bark() {
    alert('bark');
  }

}

这比我更方便如上所述,但事实证明, extends 还使用内部等效于 Object.create 来设置继承。请参阅 ES6草案中的步骤2和3。

这意味着在ES5中使用 Object.create(SuperClass.prototype)是更正确的方法。

This is more convenient than what I explained above, but as it turns out, extends also uses an internal equivalent to Object.create to setup inheritance. See steps 2 and 3 in the ES6 draft.
Which means that using Object.create(SuperClass.prototype) is the "more correct" approach in ES5.

这篇关于使用`Object.create`进行继承的好处的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆