An example of prototypical inheritance that does not involve modeling classical inheritance?

I read the following QAs, and they all explore the use of prototypal inheritance to simulate classic inheritance.

Good JavaScript prototype inheritance example

Javascript inheritance

Using JavaScript inheritance patterns

Is there one working example of prototypical inheritance in the wild? Maybe imitate life forms? What problems, apart from those that were created or were not properly resolved in the programming language, will benefit from unprocessed prototypical inheritance?

+6
javascript prototype lua
source share
4 answers

Inheritance is inheritance, so you can get the same basic functionality.

One of the advantages of prototypal inheritance in JavaScript is the ability to dynamically add new methods or change old ones available for all objects (without adding a memory penalty for each object).

This can be dangerous, especially when built-in methods, such as String or Object, have built-in methods that are overloaded in the reverse (or threatening) call.

String.prototype.replace = function () { return 'hahaha'; }; 

But it can be powerful when some browser or library implementations are inadequate in functionality or lag in performance.

It also helps the modularity, extensibility and improvement of libraries. If you turn on the user library and find that their implementation for a particular method can be optimized, you can abandon your code without violating it, while maintaining the ability to improve it or add functions to it and use all the objects defined outside their library ( at least as soon as you start adding it to the prototype). The library can even swap implementations based on user preferences (probably this is usually not a good idea, although if it can interfere with other code using this method) or let them dynamically determine the names of the methods they want to use.

And prototype behavior even comes into play even inside a “class”, since you can take advantage of the convenience of storing directly on the object (although in such cases it is added to memory and it is probably better to just create a new class - but it can still be convenient) .

 function Dog (type) { if (type === 'poodle') { this.bark = function () { alert('(yapyapyap)'); }; } } Dog.prototype.bark = function () { alert('(woof)'); }; var muffy = new Dog('poodle'); muffy.bark(); // '(yapyapyap)' var rover = new Dog(); rover.bark(); // '(woof)' 

The fact that the prototype is one that can be dynamically changed or replaced in the prototype JavaScript approach also allows you to dynamically create new classes at runtime, unlike some more traditional languages, at least offering a more concise expression:

 function Creature () {} Creature.prototype.respire = function () { return 'oooooh'; }; function createClass (o, f) { f = f || function f () {} f.prototype = (typeof o === 'function') ? o.prototype : o.constructor.prototype; f.prototype.constructor = f; return f; } var animals = ['Dog', 'Tiger', 'Lion', 'Frog', 'Kangaroo']; animals.forEach(function (animal) { window[animal] = createClass(Creature); }); var rover = new Dog(); 

Finally, you can avoid strict ones - these are hierarchies, borrowing only what you need, but still using inherited functions:

 function createMixinClass (old, constructor, newMethods) { if (typeof constructor === 'object') { newMethods = constructor; constructor = null; } var proto = old.prototype, constructor = constructor || function () {}; for (var m in proto) { constructor.prototype[m] = proto[m]; } for (var method in newMethods) { if (!newMethods[method]) { delete constructor.prototype[method]; } else { constructor.prototype[method] = newMethods[method]; } } return constructor; } var Cat = createMixinClass(Dog, {bark:null, meow: function () {alert('meow');}}); var kitty = new Cat(); 

In short, I don’t think there is anything that can handle new types of problems, but it provides more flexibility, especially with some useful utilities that can be reused.

+6
source share

This is not an example of “learning”, but using the “real world” of prototype inheritance is jQuery plugins. $.fn is actually the prototype of the jQuery magic collection, and jQuery plugins add methods to it to add functionality to any jQuery collection.

+2
source share

There are many examples of prototype inheritance in the wild. Notably, jQuery uses it. Each time you make a jQuery selection, you use the delegate prototype to inherit jQuery methods. It is also widely used in various web applications, including the Abode Creative Cloud platform, many products from Yahoo, etc.

In fact, every implementation of classical inheritance in JavaScript actually uses prototype inheritance to simulate classical inheritance - it is necessary only as a convenience for programmers who are more familiar with classical than prototype inheritance. Prototype inheritance is so flexible that it is trivial to imitate features of classical inheritance using prototype inheritance. The converse is not true.

Prototype inheritance simply means that an object is inherited directly from another object. Here is an example:

 var switchProto = { isOn: function isOn() { return this.state; }, toggle: function toggle() { this.state = !this.state; return this; }, state: false }, switch1 = Object.create(switchProto), switch2 = Object.create(switchProto); 

Usually, the factory function is used to call Object.create() to make creating the object more convenient.

There are many problems with classical inheritance that do not exist with prototype inheritance, for example:

Classic inheritance

Tight coupling. Inheritance is the narrowest connection available in OO design. Descendant levels have a deep knowledge of their ancestral classes.

Rigid hierarchies (aka duplication as needed). Single parent hierarchies rarely describe all possible use cases. After all, all hierarchies are “wrong” for new uses — a problem that requires code duplication.

Multiple inheritance is complicated. It is often desirable to inherit from multiple parents. This process is overly complex, and its implementation is incompatible with the single inheritance process, which makes it difficult to read and understand.

Fragile architecture. Because of the tight connection, it is often difficult to reorganize a class with an “incorrect” design, since many existing functions depend on the existing design.

Gorilla / Banana challenge. Often there are parts of the parent that you do not want to inherit. The subclass allows you to override the properties of the parent, but does not allow you to choose which properties you want to inherit.

Prototype inheritance

To understand how prototype inheritance solves these problems, you must first understand that there are two different types of prototype inheritance. JavaScript supports both:

Delegation. If the property is not found in the instance, it runs on the instance of the instance instance. This allows you to distribute methods among many cases, providing you with a free fly template.

concatenation. The ability to dynamically add properties to an object allows you to freely copy any properties from one object to another, all together or selectively.

You can combine both forms of prototype inheritance to achieve a very flexible code reuse system. In fact, it is so flexible that it is trivial to implement classical inheritance with prototypes. The converse is not true.

Prototype inheritance allows you to use most of the important functions that you will find in classical languages. In JavaScript, the close and factory functions allow you to implement a private state, and functional inheritance can be easily combined with prototypes to add mixes that maintain data privacy.

Some advantages of prototype inheritance:

Free communication. An instance never needs a direct reference to the parent class or prototype. It is possible to keep a reference to the prototype of the object, but it is not recommended, because it will contribute to tight communication in the hierarchy of objects - one of the biggest errors of classical inheritance.

Flat hierarchies. This is trivial with the OO prototype to keep inheritance hierarchies flat - using concatenation and delegation, you can have one level of delegation of objects and one instance without references to parent classes.

Trivial multiple inheritance. Inheriting from multiple ancestors is as simple as combining the properties of several prototypes using concatenation to create a new object or a new delegate for a new object.

Flexible architecture. Since you can selectively inherit from the OO prototype, you don’t have to worry about the “wrong design” problem. A new class can inherit any combination of properties from any combination of source objects. Due to the simple alignment of the hierarchy, a change in one place does not necessarily cause ripples in the long chain of descendants.

No more gorillas. Selective inheritance eliminates the problem of gorilla banana.

I do not know what the advantage of classical inheritance over prototype inheritance. If anyone knows about anyone, please enlighten me.

+2
source share

There are some interesting links to the Self Language Blog , including some videos.

+1
source share

All Articles