原型继承比古典继承的好处?

时间:2021-06-06 21:02:39

So I finally stopped dragging my feet all these years and decided to learn JavaScript "properly". One of the most head-scratching elements of the languages design is it's implementation of inheritance. Having experience in Ruby, I was really happy to see closures and dynamic typing; but for the life of me can't figure out what benefits are to be had from object instances using other instances for inheritance.

所以这些年来我终于不再拖拖拉拉了,我决定“适当地”学习JavaScript。语言设计中最让人挠头的元素之一是继承的实现。有过Ruby的经验,我很高兴看到闭包和动态类型;但就我个人而言,我不知道使用其他实例进行继承可以从对象实例中获得什么好处。

6 个解决方案

#1


503  

I know that this answer is 3 years late but I really think the current answers do not provide enough information about how prototypal inheritance is better than classical inheritance.

我知道这个答案晚了三年,但我真的认为目前的答案并没有提供足够的信息说明原型继承比经典继承更好。

First let's see the most common arguments JavaScript programmers state in defence of prototypal inheritance (I'm taking these arguments from the current pool of answers):

首先,让我们看看JavaScript程序员为保护原型继承而提出的最常见的参数(我将这些参数从当前的答案池中提取):

  1. It's simple.
  2. 这很简单。
  3. It's powerful.
  4. 这是强大的。
  5. It leads to smaller, less redundant code.
  6. 它导致更小、更少的冗余代码。
  7. It's dynamic and hence it's better for dynamic languages.
  8. 它是动态的,因此它对动态语言更好。

Now these arguments are all valid, but nobody has bothered explaining why. It's like telling a child that studying Maths is important. Sure it is, but the child certainly doesn't care; and you can't make a child like Maths by saying that it's important.

现在这些观点都是正确的,但是没有人费心去解释为什么。这就像告诉孩子学习数学很重要。是的,但是孩子当然不在乎;你不能让一个孩子喜欢数学,说它很重要。

I think the problem with prototypal inheritance is that it's explained from the perspective of JavaScript. I love JavaScript, but prototypal inheritance in JavaScript is wrong. Unlike classical inheritance there are two patterns of prototypal inheritance:

我认为原型继承的问题在于它是从JavaScript的角度来解释的。我喜欢JavaScript,但是JavaScript中的原型继承是错误的。与经典继承不同,原型继承有两种模式:

  1. The prototypal pattern of prototypal inheritance.
  2. 原型继承的原型模式。
  3. The constructor pattern of prototypal inheritance.
  4. 原型继承的构造函数模式。

Unfortunately JavaScript uses the constructor pattern of prototypal inheritance. This is because when JavaScript was created, Brendan Eich (the creator of JS) wanted it to look like Java (which has classical inheritance):

不幸的是,JavaScript使用了原型继承的构造函数模式。这是因为在创建JavaScript时,Brendan Eich (JS的创建者)希望它看起来像Java(具有经典继承):

And we were pushing it as a little brother to Java, as a complementary language like Visual Basic was to C++ in Microsoft’s language families at the time.

我们把它作为一个小弟弟推向Java,作为一种补充语言,如Visual Basic,在当时微软的语言家族中是c++。

This is bad because when people use constructors in JavaScript they think of constructors inheriting from other constructors. This is wrong. In prototypal inheritance objects inherit from other objects. Constructors never come into the picture. This is what confuses most people.

这很糟糕,因为当人们在JavaScript中使用构造函数时,他们会想到从其他构造函数继承的构造函数。这是错误的。在原型继承中,对象从其他对象继承。构造函数从来没有出现过。这就是让大多数人困惑的地方。

People from languages like Java, which has classical inheritance, get even more confused because although constructors look like classes they don't behave like classes. As Douglas Crockford stated:

来自Java等具有经典继承的语言的人们会更加困惑,因为尽管构造函数看起来像类,但它们并不像类。正如道格拉斯Crockford所说:

This indirection was intended to make the language seem more familiar to classically trained programmers, but failed to do that, as we can see from the very low opinion Java programmers have of JavaScript. JavaScript’s constructor pattern did not appeal to the classical crowd. It also obscured JavaScript’s true prototypal nature. As a result, there are very few programmers who know how to use the language effectively.

这种间接的目的是使语言对受过传统训练的程序员来说更熟悉,但是失败了,我们可以从Java程序员对JavaScript的低评价中看到这一点。JavaScript的构造函数模式并不受传统人群的欢迎。它也掩盖了JavaScript真正的原型性质。因此,很少有程序员知道如何有效地使用这种语言。

There you have it. Straight from the horse's mouth.

你拥有它。直接从马嘴里说出来。

True Prototypal Inheritance

Prototypal inheritance is all about objects. Objects inherit properties from other objects. That's all there is to it. There are two ways of creating objects using prototypal inheritance:

原型继承是关于对象的。对象从其他对象继承属性。这就是一切。有两种使用原型继承创建对象的方法:

  1. Create a brand new object.
  2. 创建一个全新的对象。
  3. Clone an existing object and extend it.
  4. 克隆现有对象并对其进行扩展。

Note: JavaScript offers two ways to clone an object - delegation and concatenation. Henceforth I'll use the word "clone" to exclusively refer to inheritance via delegation, and the word "copy" to exclusively refer to inheritance via concatenation.

注意:JavaScript提供了两种克隆对象的方法——委托和连接。从今往后,我将使用“克隆”一词来专门指通过委托进行继承,而“copy”一词仅指通过连接来继承遗产。

Enough talk. Let's see some examples. Say I have a circle of radius 5:

足够的讨论。让我们看看一些例子。假设有一个半径为5的圆

var circle = {
    radius: 5
};

We can calculate the area and the circumference of the circle from its radius:

我们可以从圆的半径计算圆的面积和周长:

circle.area = function () {
    var radius = this.radius;
    return Math.PI * radius * radius;
};

circle.circumference = function () {
    return 2 * Math.PI * this.radius;
};

Now I want to create another circle of radius 10. One way to do this would be:

现在我要创建另一个半径为10的圆。一种方法是:

var circle2 = {
    radius: 10,
    area: circle.area,
    circumference: circle.circumference
};

However JavaScript provides a better way - delegation. Crockford's Object.create function is used to do this:

但是JavaScript提供了一个更好的方法—委托。Crockford的对象。create函数是用来做这个的:

var circle2 = Object.create(circle);
circle2.radius = 10;

That's all. You just did prototypal inheritance in JavaScript. Wasn't that simple? You take an object, clone it, change whatever you need to, and hey presto - you got yourself a brand new object.

这是所有。你只是在JavaScript中做了原型继承。不是那么简单?你拿一个物体,克隆它,改变你需要的东西,然后,嘿,你给自己买了一个全新的物体。

Now you might ask, "How is this simple? Every time I want to create a new circle I need to clone circle and manually assign it a radius". Well the solution is to use a function to do the heavy lifting for you:

现在你可能会问,“这怎么这么简单?”每次我想要创建一个新的圆,我都需要克隆一个圆,然后手工给它分配一个半径。解决的办法是用一个函数来为你做繁重的工作:

function createCircle(radius) {
    var newCircle = Object.create(circle);
    newCircle.radius = radius;
    return newCircle;
}

var circle2 = createCircle(10);

In fact you can combine all of this into a single object literal as follows:

事实上,你可以将所有这些合并成一个单一的对象文字如下:

var circle = {
    radius: 5,
    create: function (radius) {
        var circle = Object.create(this);
        circle.radius = radius;
        return circle;
    },
    area: function () {
        var radius = this.radius;
        return Math.PI * radius * radius;
    },
    circumference: function () {
        return 2 * Math.PI * this.radius;
    }
};

var circle2 = circle.create(10);

Prototypal Inheritance in JavaScript

If you notice in the above program the create function creates a clone of circle, assigns a new radius to it and then returns it. This is exactly what a constructor does in JavaScript:

如果您在上面的程序中注意到create函数创建了一个圆的克隆,给它分配一个新的半径,然后返回它。这正是构造函数在JavaScript中的作用:

function Circle(radius) {
    this.radius = radius;
}

Circle.prototype.area = function () {
    var radius = this.radius;
    return Math.PI * radius * radius;
};

Circle.prototype.circumference = function () {         
    return 2 * Math.PI * this.radius;
};

var circle = new Circle(5);
var circle2 = new Circle(10);

The constructor pattern in JavaScript is the prototypal pattern inverted. Instead of creating an object you create a constructor. The new keyword binds the this pointer inside the constructor to a clone of the prototype of the constructor.

JavaScript中的构造函数模式是反向的原型模式。创建构造函数而不是创建对象。新的关键字将构造函数内部的指针绑定到构造函数原型的克隆上。

Sounds confusing? It's because the constructor pattern in JavaScript unnecessarily complicates things. This is what most programmers find difficult to understand.

听起来令人困惑?这是因为JavaScript中的构造函数模式不必要地使事情变得复杂。这是大多数程序员难以理解的。

Instead of thinking of objects inheriting from other objects they think of constructors inheriting from other constructors and then become utterly confused.

他们没有考虑从其他对象继承的对象,而是考虑从其他构造函数继承的构造函数,然后就完全搞不清了。

There's a whole bunch of other reasons why the constructor pattern in JavaScript should be avoided. You can read about them in my blog post here: Constructors vs Prototypes

要避免JavaScript的构造函数模式,还有很多其他原因。你可以在我的博客文章中读到:构造函数vs原型


So what are the benefits of prototypal inheritance over classical inheritance? Let's go through the most common arguments again, and explain why.

那么原型继承比经典继承有什么好处呢?让我们再看一遍最常见的论点,并解释原因。

1. Prototypal Inheritance is Simple

CMS states in his answer:

CMS在他的回答中写道:

In my opinion the major benefit of prototypal inheritance is its simplicity.

在我看来,原型继承的主要好处是它的简单性。

Let's consider what we just did. We created an object circle which had a radius of 5. Then we cloned it and gave the clone a radius of 10.

让我们考虑一下我们刚刚做了什么。我们创建了一个半径为5的物体圆。然后我们克隆了它,使它的半径为10。

Hence we only need two things to make prototypal inheritance work:

因此,我们只需要两件事就可以使原型继承工作:

  1. A way to create a new object (e.g. object literals).
  2. 创建新对象的一种方法(例如对象文字)。
  3. A way to extend an existing object (e.g. Object.create).
  4. 扩展现有对象(如object .create)的一种方法。

In contrast classical inheritance is much more complicated. In classical inheritance you have:

相比之下,古典继承要复杂得多。在古典继承中,你有:

  1. Classes.
  2. 类。
  3. Object.
  4. 对象。
  5. Interfaces.
  6. 接口。
  7. Abstract Classes.
  8. 抽象类。
  9. Final Classes.
  10. 最后一课。
  11. Virtual Base Classes.
  12. 虚拟基类。
  13. Constructors.
  14. 构造函数。
  15. Destructors.
  16. 析构函数。

You get the idea. The point is that prototypal inheritance is easier to understand, easier to implement, and easier to reason about.

你懂的。重点是原型继承更容易理解,更容易实现,更容易推理。

As Steve Yegge puts it in his classical blog post "Portrait of a N00b":

正如Steve Yegge在他的经典博客“N00b的肖像”中所说:

Metadata is any kind of description or model of something else. The comments in your code are just a a natural-language description of the computation. What makes metadata meta-data is that it's not strictly necessary. If I have a dog with some pedigree paperwork, and I lose the paperwork, I still have a perfectly valid dog.

元数据是其他东西的任何一种描述或模型。代码中的注释只是计算的自然语言描述。元数据元数据的原因是它并不是必须的。如果我养了一只狗,有一些家族式的文书工作,而我又失去了文书工作,我仍然有一只完全有效的狗。

In the same sense classes are just meta-data. Classes aren't strictly required for inheritance. However some people (usually n00bs) find classes more comfortable to work with. It gives them a false sense of security.

同样,类也是元数据。继承并不严格要求类。然而,有些人(通常是n00bs)觉得上课更舒服。它给他们一种虚假的安全感。

Well, we also know that static types are just metadata. They're a specialized kind of comment targeted at two kinds of readers: programmers and compilers. Static types tell a story about the computation, presumably to help both reader groups understand the intent of the program. But the static types can be thrown away at runtime, because in the end they're just stylized comments. They're like pedigree paperwork: it might make a certain insecure personality type happier about their dog, but the dog certainly doesn't care.

我们也知道静态类型只是元数据。它们是一种专门针对两种读者的评论:程序员和编译器。静态类型讲述一个关于计算的故事,大概是为了帮助两个读者群体理解程序的意图。但是静态类型可以在运行时丢弃,因为最终它们只是程式化的注释。它们就像是血统文件:这可能会让某个不安全的性格类型对他们的狗更开心,但狗当然不在乎。

As I stated earlier, classes give people a false sense of security. For example you get too many NullPointerExceptions in Java even when your code is perfectly legible. I find classical inheritance usually gets in the way of programming, but maybe that's just Java. Python has an amazing classical inheritance system.

正如我之前所说的,课程给人们一种错误的安全感。例如,在Java中有太多的nullpointerexception,即使您的代码非常清晰。我发现传统的继承通常会妨碍编程,但这可能只是Java。Python有一个令人惊叹的经典继承系统。

2. Prototypal Inheritance is Powerful

Most programmers who come from a classical background argue that classical inheritance is more powerful than prototypal inheritance because it has:

大多数来自古典背景的程序员认为古典继承比原型继承更强大,因为它有:

  1. Private variables.
  2. 私有变量。
  3. Multiple inheritance.
  4. 多重继承。

This claim is false. We already know that JavaScript supports private variables via closures, but what about multiple inheritance? Objects in JavaScript only have one prototype.

这种说法是错误的。我们已经知道JavaScript通过闭包支持私有变量,但是多重继承呢?JavaScript中的对象只有一个原型。

The truth is that prototypal inheritance supports inheriting from multiple prototypes. Prototypal inheritance simply means one object inheriting from another object. There are actually two ways to implement prototypal inheritance:

事实是原型继承支持从多个原型继承。原型继承仅仅意味着一个对象从另一个对象继承。实际上有两种实现原型继承的方法:

  1. Delegation or Differential Inheritance
  2. 代表团或微分继承
  3. Cloning or Concatenative Inheritance
  4. 克隆或衔接的产业

Yes JavaScript only allows objects to delegate to one other object. However it allows you to copy the properties of an arbitrary number of objects. For example _.extend does just this.

是的,JavaScript只允许对象委托给另一个对象。但是,它允许您复制任意数量对象的属性。例如_。扩展这个。

Of course many programmers don't consider this to be true inheritance because instanceof and isPrototypeOf say otherwise. However this can be easily remedied by storing an array of prototypes on every object which inherits from a prototype via concatenation:

当然,许多程序员不认为这是真正的继承,因为instanceof和isPrototypeOf则不然。但是,通过将一个原型数组存储在每个通过连接继承原型的对象上,可以很容易地解决这个问题:

function copyOf(object, prototype) {
    var prototypes = object.prototypes;
    var prototypeOf = Object.isPrototypeOf;
    return prototypes.indexOf(prototype) >= 0 ||
        prototypes.some(prototypeOf, prototype);
}

Hence prototypal inheritance is just as powerful as classical inheritance. In fact it's much more powerful than classical inheritance because in prototypal inheritance you can hand pick which properties to copy and which properties to omit from different prototypes.

因此,原型继承与经典继承一样强大。事实上,它比传统继承强大得多,因为在原型继承中,您可以从不同的原型中挑选要复制的属性和要忽略的属性。

In classical inheritance it's impossible (or at least very difficult) to choose which properties you want to inherit. They use virtual base classes and interfaces to solve the diamond problem.

在经典继承中,不可能(或至少非常困难)选择要继承的属性。它们使用虚拟基类和接口来解决diamond问题。

In JavaScript however you'll most likely never hear of the diamond problem because you can control exactly which properties you wish to inherit and from which prototypes.

然而,在JavaScript中,您很可能永远不会听到diamond问题,因为您可以精确地控制您希望继承的属性和原型。

3. Prototypal Inheritance is Less Redundant

This point is a little more difficult to explain because classical inheritance doesn't necessarily lead to more redundant code. In fact inheritance, whether classical or prototypal, is used to reduce the redundancy in code.

这一点更难解释,因为经典继承并不一定会导致更多的冗余代码。事实上,继承,不管是经典的还是原型的,都被用来减少代码中的冗余。

One argument could be that most programming languages with classical inheritance are statically typed and require the user to explicitly declare types (unlike Haskell which has implicit static typing). Hence this leads to more verbose code.

一种说法是,大多数具有古典继承的编程语言都是静态类型的,并且要求用户显式声明类型(不像Haskell那样具有隐式静态类型)。因此,这会导致更冗长的代码。

Java is notorious for this behavior. I distinctly remember Bob Nystrom mentioning the following anecdote in his blog post about Pratt Parsers:

Java因这种行为而臭名昭著。我清楚地记得鲍勃·奈斯特罗姆(Bob Nystrom)在他关于普拉特合伙人的博客文章中提到了以下轶事:

You gotta love Java's "please sign it in quadruplicate" level of bureaucracy here.

你一定喜欢Java的“请在这里签个四倍”的官僚作风。

Again, I think that's only because Java sucks so much.

再说一遍,我认为那只是因为Java太烂了。

One valid argument is that not all languages which have classical inheritance support multiple inheritance. Again Java comes to mind. Yes Java has interfaces, but that's not sufficient. Sometimes you really need multiple inheritance.

一个有效的论点是,并不是所有具有古典继承的语言都支持多重继承。我又想起了Java。是的,Java有接口,但这还不够。有时候你真的需要多重继承。

Since prototypal inheritance allows for multiple inheritance, code which requires multiple inheritance is less redundant if written using prototypal inheritance rather than in a language which has classical inheritance but no multiple inheritance.

由于原型继承允许多重继承,所以如果使用原型继承而不是在具有经典继承但没有多重继承的语言中编写需要多重继承的代码,就不会显得多余。

4. Prototypal Inheritance is Dynamic

One of the most important advantages of prototypal inheritance is that you can add new properties to prototypes after they are created. This allows you to add new methods to a prototype which will be automatically made available to all the objects which delegate to that prototype.

原型继承的一个最重要的优点是,您可以在原型创建后向原型添加新的属性。这允许您向原型添加新方法,该原型将自动提供给委托给该原型的所有对象。

This is not possible in classical inheritance because once a class is created you can't modify it at runtime. This is probably the single biggest advantage of prototypal inheritance over classical inheritance, and it should have been at the top. However I like saving the best for the end.

这在经典继承中是不可能的,因为一旦创建了类,就不能在运行时修改它。这可能是对经典继承的原型继承的最大优点,它应该在顶部。但是我喜欢把最好的留到最后。

Conclusion

Prototypal inheritance matters. It's important to educate JavaScript programmers on why to abandon the constructor pattern of prototypal inheritance in favor of the prototypal pattern of prototypal inheritance.

原型的继承问题。重要的是要教育JavaScript程序员为什么要放弃原型继承的构造函数模式,而采用原型继承的原型模式。

We need to start teaching JavaScript correctly and that means showing new programmers how to write code using the prototypal pattern instead of the constructor pattern.

我们需要正确地开始教JavaScript,这意味着向新的程序员展示如何使用原型模式而不是构造函数模式来编写代码。

Not only will it be it easier to explain prototypal inheritance using the prototypal pattern, but it will also make better programmers.

使用原型模式解释原型继承不仅更容易,而且还会使程序员更优秀。

If you liked this answer then you should also read my blog post on "Why Prototypal Inheritance Matters". Trust me, you will not be disappointed.

如果你喜欢这个答案,那么你也应该看看我关于“为什么原型继承很重要”的博文。相信我,你不会失望的。

#2


34  

Allow me to actually answer the question inline.

请允许我直接回答这个问题。

Prototype inheritance has the following virtues:

原型继承具有以下优点:

  1. It is better suited to dynamic languages because the inheritance is as dynamic as the environment it is in. (The applicability to JavaScript should be obvious here.) This permits you to do things quickly on the fly like customizing classes without huge amounts of infrastructure code.
  2. 它更适合于动态语言,因为继承与它所处的环境一样是动态的。(JavaScript的适用性在这里应该很明显。)这允许您在不需要大量基础设施代码的情况下快速地定制类。
  3. It is easier to implement a prototyping object scheme than the classic class/object dichotomy schemes.
  4. 与经典的类/对象二分方案相比,实现原型对象方案更容易。
  5. It eliminates the need for the complex sharp edges around the object model like "metaclasses" (I never metaclass I liked... sorry!) or "eigenvalues" or the like.
  6. 它不需要像“元类”(我从不喜欢的元类)这样的复杂的尖锐边缘。对不起!)或“特征值”之类的。

It has the following disadvantages however:

但它有以下缺点:

  1. Type checking a prototype language isn't impossible, but it's very, very difficult. Most "type checking" of prototypical languages is pure run-time "duck typing"-style checks. This is not suitable to all environments.
  2. 检查原型语言不是不可能的,但是非常非常困难。大多数原型语言的“类型检查”都是纯运行时的“duck typing”样式检查。这并不适用于所有的环境。
  3. It is similarly difficult to do things like optimizing method dispatch by static (or, often, even dynamic!) analysis. It can (I stress: can) be very inefficient very easily.
  4. 类似地,通过静态(通常甚至是动态)分析来优化方法分派也很困难。它可以(我强调:can)非常容易变得非常低效。
  5. Similarly object creation can be (and usually is) much slower in a prototyping language than it can be in a more conventional class/object dichotomy scheme.
  6. 类似地,在原型语言中,对象创建可以(而且通常是)比在更传统的类/对象二分方案中要慢得多。

I think you can read between the lines above and come up with the corresponding advantages and disadvantages of traditional class/object schemes. There are, of course, more in each area so I'll leave the rest up to other people answering.

我认为你可以从上面的几行中看出传统的类/对象方案的优缺点。当然,在每个区域都有更多的信息,所以我将把剩下的部分留给其他人来回答。

#3


26  

IMO the major benefit of prototypal inheritance is its simplicity.

在我看来,原型继承的主要好处是它的简单性。

The prototypal nature of the language can confuse people who are classically trained, but it turns out that actually this is a really simple and powerful concept, differential inheritance.

语言的原型性质可能会让受过古典教育的人感到困惑,但事实证明,这其实是一个非常简单而强大的概念,差别继承。

You don't need to make classification, your code is smaller, less redundant, objects inherit from other, more general objects.

您不需要进行分类,您的代码更小,冗余更少,对象继承自其他更通用的对象。

If you think prototypically you will soon notice that you don't need classes...

如果您认为原型,您将很快注意到您不需要类……

Prototypal inheritance will be much more popular in the near future, the ECMAScript 5th Edition specification introduced the Object.create method, which allows you to produce a new object instance that inherits from another one in a really simple way:

在不久的将来,原型继承将更加流行,ECMAScript第五版规范引入了对象。创建方法,它允许您生成一个新的对象实例,该实例从另一个实例中以非常简单的方式继承:

var obj = Object.create(baseInstance);

This new version of the standard is being implemented by all browser vendors, and I think we will start to see more pure prototypal inheritance...

这个新版本的标准正在由所有浏览器供应商实现,我认为我们将开始看到更多纯粹的原型继承…

#4


9  

There is really not a lot to choose between the two methods. The basic idea to grasp is that when the JavaScript engine is given a property of an object to read, it first checks the instance and if that property is missing, it checks up the prototype chain. Here is an example that shows the difference between prototypal and classical:

这两种方法之间真的没什么可选择的。要理解的基本思想是,当JavaScript引擎给定一个对象的属性来读取时,它首先检查实例,如果该属性丢失,它将检查原型链。这里有一个例子可以说明原型和古典的区别:

Prototypal

原型的

var single = { status: "Single" },
    princeWilliam = Object.create(single),
    cliffRichard = Object.create(single);

console.log(Object.keys(princeWilliam).length); // 0
console.log(Object.keys(cliffRichard).length); // 0

// Marriage event occurs
princeWilliam.status = "Married";

console.log(Object.keys(princeWilliam).length); // 1 (New instance property)
console.log(Object.keys(cliffRichard).length); // 0 (Still refers to prototype)

Classical with instance methods (Inefficient because each instance stores it's own property)

典型的实例方法(效率很低,因为每个实例都存储自己的属性)

function Single() {
    this.status = "Single";
}

var princeWilliam = new Single(),
    cliffRichard = new Single();

console.log(Object.keys(princeWilliam).length); // 1
console.log(Object.keys(cliffRichard).length); // 1

Efficient classical

有效的经典

function Single() {
}

Single.prototype.status = "Single";

var princeWilliam = new Single(),
    cliffRichard = new Single();

princeWilliam.status = "Married";

console.log(Object.keys(princeWilliam).length); // 1
console.log(Object.keys(cliffRichard).length); // 0
console.log(cliffRichard.status); // "Single"

As you can see, since it is possible to manipulate the prototype of "classes" declared in the classical style, there is really no benefit to using prototypal inheritance. It is a subset of the classical method.

正如您所看到的,由于可以操作用古典风格声明的“类”原型,因此使用原型继承实际上没有任何好处。它是经典方法的一个子集。

#5


3  

Web Development: Prototypal Inheritance vs. Classical Inheritance

Web开发:原型继承与经典继承。

http://chamnapchhorn.blogspot.com/2009/05/prototypal-inheritance-vs-classical.html

http://chamnapchhorn.blogspot.com/2009/05/prototypal-inheritance-vs-classical.html

Classical Vs prototypal inheritance - Stack Overflow

经典Vs原型继承-堆栈溢出

Classical Vs prototypal inheritance

古典与原型的继承

#6


-9  

In Javascript, with prototypal modal, you can't do instanceOf. With classical model you can. I am going to put a link here for you. www.objectplayground.com The best video that talks about Javascript prototypal.

在Javascript中,使用原型模式时,不能使用instanceOf。有了经典模型,你可以。我要在这里放一个链接。www.objectplayground.com是关于Javascript原型的最佳视频。

With ECMA 6 coming, Javascript will support the new class syntax. So TRUE classical model is coming.

随着ECMA 6的到来,Javascript将支持新的类语法。所以真正的经典模型即将出现。

The future is sticking with the classical model.

未来将坚持经典模式。

#1


503  

I know that this answer is 3 years late but I really think the current answers do not provide enough information about how prototypal inheritance is better than classical inheritance.

我知道这个答案晚了三年,但我真的认为目前的答案并没有提供足够的信息说明原型继承比经典继承更好。

First let's see the most common arguments JavaScript programmers state in defence of prototypal inheritance (I'm taking these arguments from the current pool of answers):

首先,让我们看看JavaScript程序员为保护原型继承而提出的最常见的参数(我将这些参数从当前的答案池中提取):

  1. It's simple.
  2. 这很简单。
  3. It's powerful.
  4. 这是强大的。
  5. It leads to smaller, less redundant code.
  6. 它导致更小、更少的冗余代码。
  7. It's dynamic and hence it's better for dynamic languages.
  8. 它是动态的,因此它对动态语言更好。

Now these arguments are all valid, but nobody has bothered explaining why. It's like telling a child that studying Maths is important. Sure it is, but the child certainly doesn't care; and you can't make a child like Maths by saying that it's important.

现在这些观点都是正确的,但是没有人费心去解释为什么。这就像告诉孩子学习数学很重要。是的,但是孩子当然不在乎;你不能让一个孩子喜欢数学,说它很重要。

I think the problem with prototypal inheritance is that it's explained from the perspective of JavaScript. I love JavaScript, but prototypal inheritance in JavaScript is wrong. Unlike classical inheritance there are two patterns of prototypal inheritance:

我认为原型继承的问题在于它是从JavaScript的角度来解释的。我喜欢JavaScript,但是JavaScript中的原型继承是错误的。与经典继承不同,原型继承有两种模式:

  1. The prototypal pattern of prototypal inheritance.
  2. 原型继承的原型模式。
  3. The constructor pattern of prototypal inheritance.
  4. 原型继承的构造函数模式。

Unfortunately JavaScript uses the constructor pattern of prototypal inheritance. This is because when JavaScript was created, Brendan Eich (the creator of JS) wanted it to look like Java (which has classical inheritance):

不幸的是,JavaScript使用了原型继承的构造函数模式。这是因为在创建JavaScript时,Brendan Eich (JS的创建者)希望它看起来像Java(具有经典继承):

And we were pushing it as a little brother to Java, as a complementary language like Visual Basic was to C++ in Microsoft’s language families at the time.

我们把它作为一个小弟弟推向Java,作为一种补充语言,如Visual Basic,在当时微软的语言家族中是c++。

This is bad because when people use constructors in JavaScript they think of constructors inheriting from other constructors. This is wrong. In prototypal inheritance objects inherit from other objects. Constructors never come into the picture. This is what confuses most people.

这很糟糕,因为当人们在JavaScript中使用构造函数时,他们会想到从其他构造函数继承的构造函数。这是错误的。在原型继承中,对象从其他对象继承。构造函数从来没有出现过。这就是让大多数人困惑的地方。

People from languages like Java, which has classical inheritance, get even more confused because although constructors look like classes they don't behave like classes. As Douglas Crockford stated:

来自Java等具有经典继承的语言的人们会更加困惑,因为尽管构造函数看起来像类,但它们并不像类。正如道格拉斯Crockford所说:

This indirection was intended to make the language seem more familiar to classically trained programmers, but failed to do that, as we can see from the very low opinion Java programmers have of JavaScript. JavaScript’s constructor pattern did not appeal to the classical crowd. It also obscured JavaScript’s true prototypal nature. As a result, there are very few programmers who know how to use the language effectively.

这种间接的目的是使语言对受过传统训练的程序员来说更熟悉,但是失败了,我们可以从Java程序员对JavaScript的低评价中看到这一点。JavaScript的构造函数模式并不受传统人群的欢迎。它也掩盖了JavaScript真正的原型性质。因此,很少有程序员知道如何有效地使用这种语言。

There you have it. Straight from the horse's mouth.

你拥有它。直接从马嘴里说出来。

True Prototypal Inheritance

Prototypal inheritance is all about objects. Objects inherit properties from other objects. That's all there is to it. There are two ways of creating objects using prototypal inheritance:

原型继承是关于对象的。对象从其他对象继承属性。这就是一切。有两种使用原型继承创建对象的方法:

  1. Create a brand new object.
  2. 创建一个全新的对象。
  3. Clone an existing object and extend it.
  4. 克隆现有对象并对其进行扩展。

Note: JavaScript offers two ways to clone an object - delegation and concatenation. Henceforth I'll use the word "clone" to exclusively refer to inheritance via delegation, and the word "copy" to exclusively refer to inheritance via concatenation.

注意:JavaScript提供了两种克隆对象的方法——委托和连接。从今往后,我将使用“克隆”一词来专门指通过委托进行继承,而“copy”一词仅指通过连接来继承遗产。

Enough talk. Let's see some examples. Say I have a circle of radius 5:

足够的讨论。让我们看看一些例子。假设有一个半径为5的圆

var circle = {
    radius: 5
};

We can calculate the area and the circumference of the circle from its radius:

我们可以从圆的半径计算圆的面积和周长:

circle.area = function () {
    var radius = this.radius;
    return Math.PI * radius * radius;
};

circle.circumference = function () {
    return 2 * Math.PI * this.radius;
};

Now I want to create another circle of radius 10. One way to do this would be:

现在我要创建另一个半径为10的圆。一种方法是:

var circle2 = {
    radius: 10,
    area: circle.area,
    circumference: circle.circumference
};

However JavaScript provides a better way - delegation. Crockford's Object.create function is used to do this:

但是JavaScript提供了一个更好的方法—委托。Crockford的对象。create函数是用来做这个的:

var circle2 = Object.create(circle);
circle2.radius = 10;

That's all. You just did prototypal inheritance in JavaScript. Wasn't that simple? You take an object, clone it, change whatever you need to, and hey presto - you got yourself a brand new object.

这是所有。你只是在JavaScript中做了原型继承。不是那么简单?你拿一个物体,克隆它,改变你需要的东西,然后,嘿,你给自己买了一个全新的物体。

Now you might ask, "How is this simple? Every time I want to create a new circle I need to clone circle and manually assign it a radius". Well the solution is to use a function to do the heavy lifting for you:

现在你可能会问,“这怎么这么简单?”每次我想要创建一个新的圆,我都需要克隆一个圆,然后手工给它分配一个半径。解决的办法是用一个函数来为你做繁重的工作:

function createCircle(radius) {
    var newCircle = Object.create(circle);
    newCircle.radius = radius;
    return newCircle;
}

var circle2 = createCircle(10);

In fact you can combine all of this into a single object literal as follows:

事实上,你可以将所有这些合并成一个单一的对象文字如下:

var circle = {
    radius: 5,
    create: function (radius) {
        var circle = Object.create(this);
        circle.radius = radius;
        return circle;
    },
    area: function () {
        var radius = this.radius;
        return Math.PI * radius * radius;
    },
    circumference: function () {
        return 2 * Math.PI * this.radius;
    }
};

var circle2 = circle.create(10);

Prototypal Inheritance in JavaScript

If you notice in the above program the create function creates a clone of circle, assigns a new radius to it and then returns it. This is exactly what a constructor does in JavaScript:

如果您在上面的程序中注意到create函数创建了一个圆的克隆,给它分配一个新的半径,然后返回它。这正是构造函数在JavaScript中的作用:

function Circle(radius) {
    this.radius = radius;
}

Circle.prototype.area = function () {
    var radius = this.radius;
    return Math.PI * radius * radius;
};

Circle.prototype.circumference = function () {         
    return 2 * Math.PI * this.radius;
};

var circle = new Circle(5);
var circle2 = new Circle(10);

The constructor pattern in JavaScript is the prototypal pattern inverted. Instead of creating an object you create a constructor. The new keyword binds the this pointer inside the constructor to a clone of the prototype of the constructor.

JavaScript中的构造函数模式是反向的原型模式。创建构造函数而不是创建对象。新的关键字将构造函数内部的指针绑定到构造函数原型的克隆上。

Sounds confusing? It's because the constructor pattern in JavaScript unnecessarily complicates things. This is what most programmers find difficult to understand.

听起来令人困惑?这是因为JavaScript中的构造函数模式不必要地使事情变得复杂。这是大多数程序员难以理解的。

Instead of thinking of objects inheriting from other objects they think of constructors inheriting from other constructors and then become utterly confused.

他们没有考虑从其他对象继承的对象,而是考虑从其他构造函数继承的构造函数,然后就完全搞不清了。

There's a whole bunch of other reasons why the constructor pattern in JavaScript should be avoided. You can read about them in my blog post here: Constructors vs Prototypes

要避免JavaScript的构造函数模式,还有很多其他原因。你可以在我的博客文章中读到:构造函数vs原型


So what are the benefits of prototypal inheritance over classical inheritance? Let's go through the most common arguments again, and explain why.

那么原型继承比经典继承有什么好处呢?让我们再看一遍最常见的论点,并解释原因。

1. Prototypal Inheritance is Simple

CMS states in his answer:

CMS在他的回答中写道:

In my opinion the major benefit of prototypal inheritance is its simplicity.

在我看来,原型继承的主要好处是它的简单性。

Let's consider what we just did. We created an object circle which had a radius of 5. Then we cloned it and gave the clone a radius of 10.

让我们考虑一下我们刚刚做了什么。我们创建了一个半径为5的物体圆。然后我们克隆了它,使它的半径为10。

Hence we only need two things to make prototypal inheritance work:

因此,我们只需要两件事就可以使原型继承工作:

  1. A way to create a new object (e.g. object literals).
  2. 创建新对象的一种方法(例如对象文字)。
  3. A way to extend an existing object (e.g. Object.create).
  4. 扩展现有对象(如object .create)的一种方法。

In contrast classical inheritance is much more complicated. In classical inheritance you have:

相比之下,古典继承要复杂得多。在古典继承中,你有:

  1. Classes.
  2. 类。
  3. Object.
  4. 对象。
  5. Interfaces.
  6. 接口。
  7. Abstract Classes.
  8. 抽象类。
  9. Final Classes.
  10. 最后一课。
  11. Virtual Base Classes.
  12. 虚拟基类。
  13. Constructors.
  14. 构造函数。
  15. Destructors.
  16. 析构函数。

You get the idea. The point is that prototypal inheritance is easier to understand, easier to implement, and easier to reason about.

你懂的。重点是原型继承更容易理解,更容易实现,更容易推理。

As Steve Yegge puts it in his classical blog post "Portrait of a N00b":

正如Steve Yegge在他的经典博客“N00b的肖像”中所说:

Metadata is any kind of description or model of something else. The comments in your code are just a a natural-language description of the computation. What makes metadata meta-data is that it's not strictly necessary. If I have a dog with some pedigree paperwork, and I lose the paperwork, I still have a perfectly valid dog.

元数据是其他东西的任何一种描述或模型。代码中的注释只是计算的自然语言描述。元数据元数据的原因是它并不是必须的。如果我养了一只狗,有一些家族式的文书工作,而我又失去了文书工作,我仍然有一只完全有效的狗。

In the same sense classes are just meta-data. Classes aren't strictly required for inheritance. However some people (usually n00bs) find classes more comfortable to work with. It gives them a false sense of security.

同样,类也是元数据。继承并不严格要求类。然而,有些人(通常是n00bs)觉得上课更舒服。它给他们一种虚假的安全感。

Well, we also know that static types are just metadata. They're a specialized kind of comment targeted at two kinds of readers: programmers and compilers. Static types tell a story about the computation, presumably to help both reader groups understand the intent of the program. But the static types can be thrown away at runtime, because in the end they're just stylized comments. They're like pedigree paperwork: it might make a certain insecure personality type happier about their dog, but the dog certainly doesn't care.

我们也知道静态类型只是元数据。它们是一种专门针对两种读者的评论:程序员和编译器。静态类型讲述一个关于计算的故事,大概是为了帮助两个读者群体理解程序的意图。但是静态类型可以在运行时丢弃,因为最终它们只是程式化的注释。它们就像是血统文件:这可能会让某个不安全的性格类型对他们的狗更开心,但狗当然不在乎。

As I stated earlier, classes give people a false sense of security. For example you get too many NullPointerExceptions in Java even when your code is perfectly legible. I find classical inheritance usually gets in the way of programming, but maybe that's just Java. Python has an amazing classical inheritance system.

正如我之前所说的,课程给人们一种错误的安全感。例如,在Java中有太多的nullpointerexception,即使您的代码非常清晰。我发现传统的继承通常会妨碍编程,但这可能只是Java。Python有一个令人惊叹的经典继承系统。

2. Prototypal Inheritance is Powerful

Most programmers who come from a classical background argue that classical inheritance is more powerful than prototypal inheritance because it has:

大多数来自古典背景的程序员认为古典继承比原型继承更强大,因为它有:

  1. Private variables.
  2. 私有变量。
  3. Multiple inheritance.
  4. 多重继承。

This claim is false. We already know that JavaScript supports private variables via closures, but what about multiple inheritance? Objects in JavaScript only have one prototype.

这种说法是错误的。我们已经知道JavaScript通过闭包支持私有变量,但是多重继承呢?JavaScript中的对象只有一个原型。

The truth is that prototypal inheritance supports inheriting from multiple prototypes. Prototypal inheritance simply means one object inheriting from another object. There are actually two ways to implement prototypal inheritance:

事实是原型继承支持从多个原型继承。原型继承仅仅意味着一个对象从另一个对象继承。实际上有两种实现原型继承的方法:

  1. Delegation or Differential Inheritance
  2. 代表团或微分继承
  3. Cloning or Concatenative Inheritance
  4. 克隆或衔接的产业

Yes JavaScript only allows objects to delegate to one other object. However it allows you to copy the properties of an arbitrary number of objects. For example _.extend does just this.

是的,JavaScript只允许对象委托给另一个对象。但是,它允许您复制任意数量对象的属性。例如_。扩展这个。

Of course many programmers don't consider this to be true inheritance because instanceof and isPrototypeOf say otherwise. However this can be easily remedied by storing an array of prototypes on every object which inherits from a prototype via concatenation:

当然,许多程序员不认为这是真正的继承,因为instanceof和isPrototypeOf则不然。但是,通过将一个原型数组存储在每个通过连接继承原型的对象上,可以很容易地解决这个问题:

function copyOf(object, prototype) {
    var prototypes = object.prototypes;
    var prototypeOf = Object.isPrototypeOf;
    return prototypes.indexOf(prototype) >= 0 ||
        prototypes.some(prototypeOf, prototype);
}

Hence prototypal inheritance is just as powerful as classical inheritance. In fact it's much more powerful than classical inheritance because in prototypal inheritance you can hand pick which properties to copy and which properties to omit from different prototypes.

因此,原型继承与经典继承一样强大。事实上,它比传统继承强大得多,因为在原型继承中,您可以从不同的原型中挑选要复制的属性和要忽略的属性。

In classical inheritance it's impossible (or at least very difficult) to choose which properties you want to inherit. They use virtual base classes and interfaces to solve the diamond problem.

在经典继承中,不可能(或至少非常困难)选择要继承的属性。它们使用虚拟基类和接口来解决diamond问题。

In JavaScript however you'll most likely never hear of the diamond problem because you can control exactly which properties you wish to inherit and from which prototypes.

然而,在JavaScript中,您很可能永远不会听到diamond问题,因为您可以精确地控制您希望继承的属性和原型。

3. Prototypal Inheritance is Less Redundant

This point is a little more difficult to explain because classical inheritance doesn't necessarily lead to more redundant code. In fact inheritance, whether classical or prototypal, is used to reduce the redundancy in code.

这一点更难解释,因为经典继承并不一定会导致更多的冗余代码。事实上,继承,不管是经典的还是原型的,都被用来减少代码中的冗余。

One argument could be that most programming languages with classical inheritance are statically typed and require the user to explicitly declare types (unlike Haskell which has implicit static typing). Hence this leads to more verbose code.

一种说法是,大多数具有古典继承的编程语言都是静态类型的,并且要求用户显式声明类型(不像Haskell那样具有隐式静态类型)。因此,这会导致更冗长的代码。

Java is notorious for this behavior. I distinctly remember Bob Nystrom mentioning the following anecdote in his blog post about Pratt Parsers:

Java因这种行为而臭名昭著。我清楚地记得鲍勃·奈斯特罗姆(Bob Nystrom)在他关于普拉特合伙人的博客文章中提到了以下轶事:

You gotta love Java's "please sign it in quadruplicate" level of bureaucracy here.

你一定喜欢Java的“请在这里签个四倍”的官僚作风。

Again, I think that's only because Java sucks so much.

再说一遍,我认为那只是因为Java太烂了。

One valid argument is that not all languages which have classical inheritance support multiple inheritance. Again Java comes to mind. Yes Java has interfaces, but that's not sufficient. Sometimes you really need multiple inheritance.

一个有效的论点是,并不是所有具有古典继承的语言都支持多重继承。我又想起了Java。是的,Java有接口,但这还不够。有时候你真的需要多重继承。

Since prototypal inheritance allows for multiple inheritance, code which requires multiple inheritance is less redundant if written using prototypal inheritance rather than in a language which has classical inheritance but no multiple inheritance.

由于原型继承允许多重继承,所以如果使用原型继承而不是在具有经典继承但没有多重继承的语言中编写需要多重继承的代码,就不会显得多余。

4. Prototypal Inheritance is Dynamic

One of the most important advantages of prototypal inheritance is that you can add new properties to prototypes after they are created. This allows you to add new methods to a prototype which will be automatically made available to all the objects which delegate to that prototype.

原型继承的一个最重要的优点是,您可以在原型创建后向原型添加新的属性。这允许您向原型添加新方法,该原型将自动提供给委托给该原型的所有对象。

This is not possible in classical inheritance because once a class is created you can't modify it at runtime. This is probably the single biggest advantage of prototypal inheritance over classical inheritance, and it should have been at the top. However I like saving the best for the end.

这在经典继承中是不可能的,因为一旦创建了类,就不能在运行时修改它。这可能是对经典继承的原型继承的最大优点,它应该在顶部。但是我喜欢把最好的留到最后。

Conclusion

Prototypal inheritance matters. It's important to educate JavaScript programmers on why to abandon the constructor pattern of prototypal inheritance in favor of the prototypal pattern of prototypal inheritance.

原型的继承问题。重要的是要教育JavaScript程序员为什么要放弃原型继承的构造函数模式,而采用原型继承的原型模式。

We need to start teaching JavaScript correctly and that means showing new programmers how to write code using the prototypal pattern instead of the constructor pattern.

我们需要正确地开始教JavaScript,这意味着向新的程序员展示如何使用原型模式而不是构造函数模式来编写代码。

Not only will it be it easier to explain prototypal inheritance using the prototypal pattern, but it will also make better programmers.

使用原型模式解释原型继承不仅更容易,而且还会使程序员更优秀。

If you liked this answer then you should also read my blog post on "Why Prototypal Inheritance Matters". Trust me, you will not be disappointed.

如果你喜欢这个答案,那么你也应该看看我关于“为什么原型继承很重要”的博文。相信我,你不会失望的。

#2


34  

Allow me to actually answer the question inline.

请允许我直接回答这个问题。

Prototype inheritance has the following virtues:

原型继承具有以下优点:

  1. It is better suited to dynamic languages because the inheritance is as dynamic as the environment it is in. (The applicability to JavaScript should be obvious here.) This permits you to do things quickly on the fly like customizing classes without huge amounts of infrastructure code.
  2. 它更适合于动态语言,因为继承与它所处的环境一样是动态的。(JavaScript的适用性在这里应该很明显。)这允许您在不需要大量基础设施代码的情况下快速地定制类。
  3. It is easier to implement a prototyping object scheme than the classic class/object dichotomy schemes.
  4. 与经典的类/对象二分方案相比,实现原型对象方案更容易。
  5. It eliminates the need for the complex sharp edges around the object model like "metaclasses" (I never metaclass I liked... sorry!) or "eigenvalues" or the like.
  6. 它不需要像“元类”(我从不喜欢的元类)这样的复杂的尖锐边缘。对不起!)或“特征值”之类的。

It has the following disadvantages however:

但它有以下缺点:

  1. Type checking a prototype language isn't impossible, but it's very, very difficult. Most "type checking" of prototypical languages is pure run-time "duck typing"-style checks. This is not suitable to all environments.
  2. 检查原型语言不是不可能的,但是非常非常困难。大多数原型语言的“类型检查”都是纯运行时的“duck typing”样式检查。这并不适用于所有的环境。
  3. It is similarly difficult to do things like optimizing method dispatch by static (or, often, even dynamic!) analysis. It can (I stress: can) be very inefficient very easily.
  4. 类似地,通过静态(通常甚至是动态)分析来优化方法分派也很困难。它可以(我强调:can)非常容易变得非常低效。
  5. Similarly object creation can be (and usually is) much slower in a prototyping language than it can be in a more conventional class/object dichotomy scheme.
  6. 类似地,在原型语言中,对象创建可以(而且通常是)比在更传统的类/对象二分方案中要慢得多。

I think you can read between the lines above and come up with the corresponding advantages and disadvantages of traditional class/object schemes. There are, of course, more in each area so I'll leave the rest up to other people answering.

我认为你可以从上面的几行中看出传统的类/对象方案的优缺点。当然,在每个区域都有更多的信息,所以我将把剩下的部分留给其他人来回答。

#3


26  

IMO the major benefit of prototypal inheritance is its simplicity.

在我看来,原型继承的主要好处是它的简单性。

The prototypal nature of the language can confuse people who are classically trained, but it turns out that actually this is a really simple and powerful concept, differential inheritance.

语言的原型性质可能会让受过古典教育的人感到困惑,但事实证明,这其实是一个非常简单而强大的概念,差别继承。

You don't need to make classification, your code is smaller, less redundant, objects inherit from other, more general objects.

您不需要进行分类,您的代码更小,冗余更少,对象继承自其他更通用的对象。

If you think prototypically you will soon notice that you don't need classes...

如果您认为原型,您将很快注意到您不需要类……

Prototypal inheritance will be much more popular in the near future, the ECMAScript 5th Edition specification introduced the Object.create method, which allows you to produce a new object instance that inherits from another one in a really simple way:

在不久的将来,原型继承将更加流行,ECMAScript第五版规范引入了对象。创建方法,它允许您生成一个新的对象实例,该实例从另一个实例中以非常简单的方式继承:

var obj = Object.create(baseInstance);

This new version of the standard is being implemented by all browser vendors, and I think we will start to see more pure prototypal inheritance...

这个新版本的标准正在由所有浏览器供应商实现,我认为我们将开始看到更多纯粹的原型继承…

#4


9  

There is really not a lot to choose between the two methods. The basic idea to grasp is that when the JavaScript engine is given a property of an object to read, it first checks the instance and if that property is missing, it checks up the prototype chain. Here is an example that shows the difference between prototypal and classical:

这两种方法之间真的没什么可选择的。要理解的基本思想是,当JavaScript引擎给定一个对象的属性来读取时,它首先检查实例,如果该属性丢失,它将检查原型链。这里有一个例子可以说明原型和古典的区别:

Prototypal

原型的

var single = { status: "Single" },
    princeWilliam = Object.create(single),
    cliffRichard = Object.create(single);

console.log(Object.keys(princeWilliam).length); // 0
console.log(Object.keys(cliffRichard).length); // 0

// Marriage event occurs
princeWilliam.status = "Married";

console.log(Object.keys(princeWilliam).length); // 1 (New instance property)
console.log(Object.keys(cliffRichard).length); // 0 (Still refers to prototype)

Classical with instance methods (Inefficient because each instance stores it's own property)

典型的实例方法(效率很低,因为每个实例都存储自己的属性)

function Single() {
    this.status = "Single";
}

var princeWilliam = new Single(),
    cliffRichard = new Single();

console.log(Object.keys(princeWilliam).length); // 1
console.log(Object.keys(cliffRichard).length); // 1

Efficient classical

有效的经典

function Single() {
}

Single.prototype.status = "Single";

var princeWilliam = new Single(),
    cliffRichard = new Single();

princeWilliam.status = "Married";

console.log(Object.keys(princeWilliam).length); // 1
console.log(Object.keys(cliffRichard).length); // 0
console.log(cliffRichard.status); // "Single"

As you can see, since it is possible to manipulate the prototype of "classes" declared in the classical style, there is really no benefit to using prototypal inheritance. It is a subset of the classical method.

正如您所看到的,由于可以操作用古典风格声明的“类”原型,因此使用原型继承实际上没有任何好处。它是经典方法的一个子集。

#5


3  

Web Development: Prototypal Inheritance vs. Classical Inheritance

Web开发:原型继承与经典继承。

http://chamnapchhorn.blogspot.com/2009/05/prototypal-inheritance-vs-classical.html

http://chamnapchhorn.blogspot.com/2009/05/prototypal-inheritance-vs-classical.html

Classical Vs prototypal inheritance - Stack Overflow

经典Vs原型继承-堆栈溢出

Classical Vs prototypal inheritance

古典与原型的继承

#6


-9  

In Javascript, with prototypal modal, you can't do instanceOf. With classical model you can. I am going to put a link here for you. www.objectplayground.com The best video that talks about Javascript prototypal.

在Javascript中,使用原型模式时,不能使用instanceOf。有了经典模型,你可以。我要在这里放一个链接。www.objectplayground.com是关于Javascript原型的最佳视频。

With ECMA 6 coming, Javascript will support the new class syntax. So TRUE classical model is coming.

随着ECMA 6的到来,Javascript将支持新的类语法。所以真正的经典模型即将出现。

The future is sticking with the classical model.

未来将坚持经典模式。