Inheritance in JavaScript is quite weird. It cannot implement interface inheritance and can only rely on prototype inheritance.
Prototype chain
A prototype is an object. The instance created through the constructor will have a pointer to the prototype to obtain the properties and methods of the prototype. In this way, the instance object has the attribute method of the constructor and the attribute method of the prototype, and then points the prototype of the constructor that needs to be inherited to this instance, so that all the attribute methods of the instance can be inherited.
See the following demo code:
//Declare the superclass, add relevant properties and methods through constructors and prototypes function Super(){ this.property = true;}Super.prototype.getSuperValue = function() { return this.property;};//Declare the constructor function SubType() { this.subproperty = false;}//Point the prototype of the subclass to the instance of the superclass and get everything in the superclass SubType.prototype = new Super();SubType.prototype.constructor = SubType;SubType.prototype.getSubValue = function(){ return this.subproperty;};//Create an object from a subclass to test whether to inherit superclass methods and attributes var instance = new SubType(); console.log(instance.getSuperValue());The default prototype of all functions is an instance of Object, so the default prototype will contain an internal pointer to Object.prototype.
Use instanceof and isPrototypeOf to determine the relationship between prototypes and instances:
instance instance of Object;Object.prototype.isPrototypeOf(instance);
When using prototype chains, you need to define the method carefully. Subclasses need to rewrite a method or extension of supertype, and must be placed after the statement that replaces the prototype, so that it can take effect. In addition, when inheriting through a prototype chain, you cannot use object literals to create a prototype method, which will override the prototype chain:
......SubType.prototype = new Super();SubType.prototype = { ....};This replaces the pointer to point to the new object, rewriting the prototype chain.
The inheritance method of prototype chains is flawed, and there are two main problems:
1. From a prototype containing the reference type value, it will be shared by all instances.
As mentioned in the previous article, the prototype attributes containing reference type values will be shared by all instances. One instance will be modified and the other instances will change accordingly. Therefore, the attributes need to be defined in the constructor. When the prototype chain inherits, no matter whether the attributes in the superclass are defined in the constructor or the prototype, all become instance objects and are inherited by subclasses, thus having an impact on the instances of the subclass.
2. When creating an instance of a subtype, parameters cannot be passed to the supertype constructor.
The inheritance of the prototype chain directly points the subclass prototype to the instance of the superclass, and at this time, parameters can be passed to the superclass. However, when a subclass creates an instance, it can only pass parameters to the constructor of the subclass, but not to the constructor of the superclass.
Therefore, in practical applications, prototype chains are rarely used alone.
Some related code practices
Identify a prototype attribute
function hasPrototypeProperty(object, name) { return name in object && !object.hasOwnProperty(name);}Using prototype objects in constructors
function Person(name) { this.name = name;}Person.prototype = { constructor: Person, sayName: function () { console.log(this.name); }, toString: function() { }};var person1 = new Person('Nicholas');var person2 = new Person('Greg);console.log(person1 instanceof Person); // trueconsole.log(person1.constructor === Person); // trueconsole.log(person1.constructor === Person); // trueconsole.log(person1.constructor === Object); // falseconsole.log(person2 instanceof Person); // trueconsole.log(person2.constructor === Person); // trueconsole.log(person2.constructor === Object); // falseObject inheritance
var person1 = { name: 'Nicholas', sayName: function () { console.log(this.name); }};var person2 = Object.create(person1, { name: { configurable: true, enumerable: true, value: 'Greg', writable: true }});person1.sayName(); // Nicholasperson2.sayName(); // Gregconsole.log(person1.hasOwnProperty('sayName')); // trueconsole.log(person1.isPropertyOf(person2)); // trueconsole.log(person2.hasOwnProperty('sayName')); // falseModule mode
var person = (function () { var age = 25; function getAge() { return age; } function growOlder() { age++; } return { name: 'Nicholas', getAge: getAge, growOlder: growOlder };}());Scope constructor
function Person(name) { this.name = name;}Person.prototype.sayName = function() { console.log(this.name);};var person1 = Person('Nicholas');console.log(person1 instanceof Person); // falseconsole.log(typeof person1); // undefinedconsole.log(name); // Nicholas