The concept most often discussed in relation to OO programming is inheritance. Many OO languages support two types of inheritance: interface inheritance, where only the method signatures are inherited, and implementation inheritance, where actual methods are inherited. Interface inheritance is not possible in ECMAScript, because functions do not have signatures. Implementation inheritance is the only type of inheritance supported by ECMAScript, and this is done primarily through the use of prototype chaining.
Prototype Chaining
ECMA-262 describes prototype chaining as the primary method of inheritance in ECMAScript. The basic idea is to use the concept of prototypes to inherit properties and methods between two reference types. Recall the relationship between constructors, prototypes, and instances: each constructor has a prototype object that points back to the constructor, and instances have an internal pointer to the prototype. What if the prototype were actually an instance of another type? That would mean the prototype itself would have a pointer to a different prototype that, in turn, would have a pointer to another constructor. If that prototype were also an instance of another type, then the pattern would continue, forming a chain between instances and prototypes. This is the basic idea behind prototype chaining.
function SuperType() { this.property = true; } SuperType.prototype.getSuperValue = function() { return this.property; }; function SubType() { this.subproperty = false; } //inherit from SuperType SubType.prototype = new SuperType(); //new method SubType.prototype.getSubValue = function() { return this.subproperty; }; //override existing method SubType.prototype.getSuperValue = function() { return false; }; var instance = new SubType(); alert(instance.getSuperValue()); //false
Even though prototype chaining is a powerful tool for inheritance, it is not without its issues. The major issue revolves around prototypes that contain reference values. Recall from earlier that prototype properties containing reference values are shared with all instances; this is why properties are typically defined within the constructor instead of on the prototype. When implementing inheritance using prototypes, the prototype actually becomes an instance of another type, meaning that what once were instance properties are now prototype properties.
A second issue with prototype chaining is that you cannot pass arguments into the supertype constructor when the subtype instance is being created. In fact, there is no way to pass arguments into the supertype constructor without affecting all of the object instances. Because of this and the aforementioned issue with reference values on the prototype, prototype chaining is rarely used alone.
Constructor Stealing
In an attempt to solve the inheritance problem with reference values on prototypes, developers began using a technique called constructor stealing (also sometimes called object masquerading or classical inheritance). The basic idea is quite simple: call the supertype constructor from within the subtype constructor. Keeping in mind that functions are simply objects that execute code in a particular context, the apply() and call() methods can be used to execute a constructor on the newly created object.
function SuperType(name) { this.name = name; } function SubType() { //inherit from SuperType passing in an argument SuperType.call(this, "Nicholas"); // instance property this.age = 29; } var instance = new SubType(); alert(instance.name); //"Nicholas"; alert(instance.age); //29
The downside to using constructor stealing exclusively is that it introduces the same problems as the constructor pattern for custom types: methods must be defined inside the constructor, so there’s no function reuse. Furthermore, methods defined on the supertype’s prototype are not accessible on the subtype, so all types can use only the constructor pattern. Because of these issues, constructor stealing is rarely used on its own.
Combination Inheritance
Combination inheritance (sometimes also called pseudoclassical inheritance) combines prototype chaining and constructor stealing to get the best of each approach. The basic idea is to use prototype chaining to inherit properties and methods on the prototype and to use constructor stealing to inherit instance properties. This allows function reuse by defining methods on the prototype and allows each instance to have its own properties.
function SuperType(name) { this.name = name; this.colors = [ "red", "blue", "green" ]; } SuperType.prototype.sayName = function() { alert(this.name); }; function SubType(name, age) { SuperType.call(this, name); this.age = age; } SubType.prototype = new SuperType(); SubType.prototype.sayAge = function() { alert(this.age); }; var instance1 = new SubType("Nicholas", 29); instance1.colors.push("black"); alert(instance1.colors); //"red,blue,green,black" instance1.sayName(); //"Nicholas"; instance1.sayAge(); //29 var instance2 = new SubType("Greg", 27); alert(instance2.colors); //"red,blue,green" instance2.sayName(); //"Greg"; instance2.sayAge(); //27
In this example, the SuperType constructor defines two properties, name and colors, and the SuperType prototype has a single method called sayName(). The SubType constructor calls the SuperType constructor, passing in the name argument, and defines its own property called age. Additionally, the SubType prototype is assigned to be an instance of SuperType, and then a new method called sayAge() is defined. With this code, it’s then possible to create two separate instances of SubType that have their own properties, including the colors property, but all use the same methods.
Addressing the downsides of both prototype chaining and constructor stealing, combination inheritance is the most frequently used inheritance pattern in JavaScript. It also preserves the behavior of instanceof and isPrototypeOf() for identifying the composition of objects.
Here gives a comprehensive example about Combination Inheritance.
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Combination Inheritance Example</title> <script type="text/javascript"> function Shape(edge) { this.edge = edge; } Shape.prototype.getArea = function() { return -1; } Shape.prototype.getEdge = function() { return this.edge; } function Triangle(bottom, height) { Shape.call(this, 3); this.bottom = bottom; this.height = height; } Triangle.prototype = new Shape(); Triangle.prototype.getArea = function() { return 0.5 * this.bottom * this.height; } //Triangle.prototype.getEdge = function() //{ // return this.edge; //} var triangle = new Triangle(10, 4); //alert(triangle.getEdge()); //alert(triangle.getArea()); function Rectangle(bottom, height) { Shape.call(this, 4); this.bottom = bottom; this.height = height; } Rectangle.prototype = new Shape(); Rectangle.prototype.getArea = function() { return this.bottom * this.height; } //Rectangle.prototype.getEdge = function() //{ // return this.edge; //} var rectangle = new Rectangle(20, 40); alert(rectangle.getEdge()); alert(rectangle.getArea()); </script> </head> <body> </body> </html>
Summary
There are total 6 approaches to implement inheritance, e.g.
- Prototype Chaining
- Constructor Stealing
- Combination Inheritance(The most common way)
- Prototypal Inheritance
- Parasitic Inheritance
- Parasitic Combination Inheritance
The most common way
function SuperType(name) { this.name = name; this.colors = ["red", "blue", "green"]; } SuperType.prototype.sayName = function () { console.log(this.name); }; function SubType(name, age) { SuperType.call(this, name); this.age = age; } SubType.prototype = new SuperType(); SubType.prototype.sayAge = function () { console.log(this.age); }; var instance1 = new SubType("Michael", 29); instance1.colors.push("black"); console.log(instance1.colors); //"red,blue,green,black" instance1.sayName(); //"Michael"; instance1.sayAge(); //29 var instance2 = new SubType("Jordan", 27); console.log(instance2.colors); //"red,blue,green" instance2.sayName(); //"Jordan"; instance2.sayAge(); //27
Reference
Wrox.Professional.javascript.for.Web.Developers.3rd.Edition.2012
Leanpub.Principles.of.Object-Oriented.Programming.in.JavaScript.Jun.2014
相关推荐
oriented features introduced in ECMAScript 6 It makes object-oriented programming accessible and understandable to web developers Write better and more maintainable JavaScript code while exploring ...
Mastering JavaScript Object-Oriented Programming 2016 | ISBN: 1785889109 | English | 287 pages | PDF | 1.9 MB With this book, we'll provide you with a comprehensive overview of OOP principles in ...
Learning Object-Oriented Programming is an easy-to-follow guide full of hands-on examples of solutions to common problems with object-oriented code in Python, JavaScript, and C#. It starts by helping ...
JavaScript developers looking to enhance their web developments skills by learning object-oriented programming. What You Will Learn Get acquainted with the basics of JavaScript language constructs ...
Object Oriented Programming with Swift 2 by Gaston C. Hillar 2016 | ISBN: 1785885693 | English | 332 pages Get to grips with object-oriented programming in Swift to efficiently build powerful real-...
and make them your own Understand objects in Google Chrome developer tools and how to use Them Use a mix of prototypal inheritance and copying properties in your workflow Apply reactive programming ...
The basics of object-oriented programming, and how to apply it in the JavaScript environment How to set up and use your training environment (Firebug) In depth discussion of data types, operators, ...
面向对象编程(Object-Oriented Programming,简称OOP)是一种编程范式,它基于“对象”的概念,将数据和操作数据的方法封装在一起。在“10-Object-Oriented-Programming-Team-Profile-Generator”项目中,我们看到...
面向对象编程(Object-Oriented Programming,简称OOP)是一种编程范式,它基于“对象”的概念,将数据和操作数据的方法封装在一起,以实现代码的模块化和可重用性。在本OOP课程中,SoftUni为学生提供了一个学习资源...
面向对象编程(Object-Oriented Programming,简称OOP)是一种编程范式,它基于对象的概念,将数据和处理数据的方法封装在一起。在JavaScript中,面向对象的实现方式主要有三种:构造函数、原型链和ES2015引入的类...
Packed with practical code samples, this book brings the benefits of strongly typed, object-oriented programming and design principles into the JavaScript development space. Starting with core ...
我们可以假设,流行的OOP语言是C ++,C#,Java,PHP,Python和JavaScript。面向对象的优点: 它使编写的代码能够被重用(Code-Reusability)。 这样,成本就降低了。 可扩展性是通过向编写的类添加新功能和方法来...
Packed with practical, real-world examples, this book is a guide to bringing the benefits of strongly typed, object-oriented programming and design principles into the JavaScript development space....
After getting an overview of JavaScript object-oriented programming (OOP) concepts and their practical usage, you should be able to write your own object definitions using the module pattern....
Chapter 3, Interfaces, Classes, and Inheritance, builds on the work from the previous chapter, and introduces the object-oriented concepts and capabilities of interfaces, classes, and inheritance....
JavaScript quick start: Familiar with object-oriented programming? This part helps you learn JavaScript quickly and properly. JavaScript in depth: Learn details of ECMAScript 5, from syntax, variables...