The example in this article introduces 6 ways to implement inheritance in JavaScript and shares it with you for your reference. The specific content is as follows
1. [Prototype Chain Inheritance] The essence of implementation is to rewrite the prototype object and replace it with an instance of a new type. In fact, it is not the constructor property of the SubType prototype that has been rewritten, but the SubType prototype points to another object - the SuperType prototype, and the constructor property of this prototype object points to SuperType
function SuperType(){ this.property = true; } SuperType.prototype.getSuperValue = function(){ return this.property; }; function SubType(){ this.subproperty = false; } //继承了SuperType SubType.prototype = new SuperType(); SubType.prototype.getSubValue = function(){ return this.subproperty; } var instance = new SubType(); alert(instance.getSuperValue());//true
[Note 1] Define methods carefully, and the code to add methods to the prototype must be placed after the statement that replaces the prototype
function SuperType(){ this.property = true; } SuperType.prototype.getSuperValue = function(){ return this.property; }; function SubType(){ this.subproperty = false; } //继承了SuperType SubType.prototype = new SuperType(); //添加了新方法 SubType.prototype.getSubValue = function(){ return this.subproperty; } //重写超类型的方法 SubType.prototype.getSuperValue = function(){ return false; } var instance = new SubType(); alert(instance.getSuperValue());//false
[Note 2] When implementing inheritance through the prototype chain, you cannot use object literals to create prototype methods. Doing so will rewrite the prototype chain
function SuperType(){ this.property = true; } SuperType.prototype.getSuperValue = function(){ return this.property; }; function SubType(){ this.subproperty = false; } //继承了SuperType SubType.prototype = new SuperType(); //使用字面量方法添加新方法会导致上一行代码无效 SubType.prototype = { getSubValue : function(){ return this,subproperty; }, someOtherMethod : function(){ return false; } }; var instance = new SubType(); alert(instance.getSuperValue());//error
[Disadvantage 1] When creating an instance of a subtype, parameters cannot be passed to the constructor of the supertype
[Disadvantage 2] Prototype properties containing reference type values will be shared by all instances
function SuperType(){ this.colors = ['red','blue','green']; } function SubType(){} //继承了SuperType SubType.prototype = new SuperType(); var instance1 = new SubType(); instance1.colors.push('black'); alert(instance1.colors);//'red,blue,green,black' var instance2 = new SubType(); alert(instance2.colors);//'red,blue,green,black'
2. [Borrowed constructor inheritance (also called fake object or classic inheritance)] calls the supertype constructor inside the subtype constructor, so by using the apply() and call() methods Constructors can also be executed on newly created objects in the future
function SuperType(){ this.colors = ['red','blue','green']; } function SubType(){ //继承了SuperType SuperType.call(this); } var instance1 = new SubType(); instance1.colors.push('black'); alert(instance1.colors);//'red,blue,green,black' var instance2 = new SubType(); alert(instance2.colors);//'red,blue,green'
[Advantages] Pass parameters
function SuperType(name){ this.name = name; } function SubType(){ //继承了SUperType,同时还传递了参数 SuperType.call(this,"Nicholas"); //实例属性 this.age = 29; } var instance = new SubType(); alert(instance.name);//"Nicholas" alert(instance.age);//29
[Note] In order to ensure that the SuperType constructor does not override the properties of the subtype, you can add properties that should be defined in the subtype after calling the supertype constructor
function SuperType(name){ this.name = name; this.age = 30; } function SubType(){ //实例属性 this.age = 29; //继承了SUperType,同时还传递了参数 SuperType.call(this,"Nicholas"); } var instance = new SubType(); //实例属性被重写为SuperType构造函数的属性 alert(instance.age);//30
[Disadvantage 1] Function reuse cannot be achieved
[Disadvantage 2] Methods defined in the prototype of the super type are also invisible to the subtype. As a result, all types can only use the constructor pattern
3. [Combined inheritance (also called pseudo-classical inheritance)] An inheritance model that combines the technology of prototype chaining and borrowing constructors to take advantage of the strengths of both. The idea behind it is to use the prototype chain to achieve inheritance of prototype properties and methods, and to achieve inheritance of instance properties by borrowing constructors. In this way, function reuse is achieved by defining methods on the prototype, and each instance can be guaranteed to have its own attributes, making it the most commonly used inheritance pattern in JavaScript.
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.constructor = SubType; 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
[Disadvantages] In any case, the supertype constructor will be called twice: once when creating the subtype prototype, and once inside the subtype constructor. The subtype will eventually contain all instance properties of the supertype object, but will have to override these properties when the subtype constructor is called.
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); // 第二次调用SuperType() this.age = age; } SubType.prototype = new SuperType(); //第一次调用SuperType() SubType.prototype.constructor = SubType; SubType.prototype.sayAge = function(){ alert(this.age); };
4. [Prototypal inheritance] Using prototypes, you can create new objects based on existing objects without having to create custom types. Essentially, object() performs a shallow copy of the object passed into it.
[Note] Prototypal inheritance requires that there must be an object that can be used as the basis of another object. If there is such an object, you can pass it to the object() function, and then modify the obtained object according to specific needs
function object(o){ function F(){}; F.prototype = o; return new F(); } var person = { name: "Nicholas", friends: ["Shelby","Court","Van"] }; var anotherPerson = object(person); anotherPerson.name = "Greg"; anotherPerson.friends.push("Rob"); var yetAnotherPerson = object(person); yetAnotherPerson.name = "Linda"; yetAnotherPerson.friends.push("Barbie"); alert(person.friends);//"Shelby,Court,Van,Rob,Barbie"
【4.1】【Object.create() method】: ECMAScript5’s new Object.create() method standardizes prototypal inheritance. This method accepts two parameters: an object to be used as the prototype of the new object and (optionally) an object to define additional properties for the new object. When a parameter is passed in, the Object.create() and object() methods behave the same
function object(o){ function F(){}; F.prototype = o; return new F(); } var person = { name: "Nicholas", friends:["Shelby","Court","Van"] }; var anotherPerson = Object.create(person); anotherPerson.name = "Greg"; anotherPerson.friends.push("Rob"); var yetAnotherPerson = object(person); yetAnotherPerson.name = "Linda"; yetAnotherPerson.friends.push("Barbie"); alert(person.friends);//"Shelby,Court,Van,Rob,Barbie"
[Note] The second parameter of the Object.create() method has the same format as the second parameter of the Object.defineProperties() method: each property is defined through its own descriptor. Any property specified in this way overrides the property of the same name on the prototype object.
var person = { name: "Nicholas", friends:["Shelby","Court","Van"] }; var anotherPerson = Object.create(person,{ name: { value: "Greg" } }); alert(anotherPerson.name);//"Greg"
【4.2】Compatible with Object.create() method in lower version browsers
if(typeof Object.create != "function"){ (function(){ var F = function(){}; Object.create = function(o){ if(arguments.length > 1){ throw Error('Second argument noe supported'); } if(o === null){ throw Error("Cannot set a null [[Prototype]]"); } if(typeof o != 'Object'){ throw TypeError("Arguments must be an object"); } F.prototype = o; return new F(); } })(); }
5. [Parasitic Inheritance] Create a function that is only used to encapsulate the inheritance process. This function enhances the object in some way internally, and finally looks like it really did all the work. Returns the same object
[Disadvantage] Function reuse cannot be achieved
function object(o){ function F(){}; F.prototype = o; return new F(); } function createAnother(original){ var clone = object(original);//通过调用函数创建一个新对象 clone.sayHi = function(){ //以某种方式来增强这个对象 alert("hi"); }; return clone;//返回这个对象 } var person = { name: "Nicholas", friends: ["Shelby","Court","Van"] }; var anotherPerson = createAnother(person); anotherPerson.sayHi();//"hi"
6. [Parasitic Combination Inheritance] Inherit properties by borrowing constructors, and inherit methods through the hybrid form of the prototype chain. The basic idea behind this is that you don't have to call the supertype's constructor to specify a subtype's prototype; all you need is a copy of the supertype's prototype. Essentially, you use parasitic inheritance to inherit from the supertype's prototype and then assign the result to the subtype's prototype. Parasitic combined inheritance is the most ideal inheritance paradigm for reference types.
//这个例子中的高效率体现在它只调用了一次Super构造函数,并且因此避免了在SubType.prototype上面创建不必要的、多余的属性。与此同时,原型链还能保持不变。 function object(o){ function F(){}; F.prototype = o; return new F(); } function inheritPrototype(subType,superType){ var prototype = object(superType.prototype);//创建对象 prototype.constructor = subType;//增强对象 subType.prototype = prototype;//指定对象 } 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; } inheritPrototype(SubType,SuperType); SubType.prototype.sayAge = function(){ alert(this.age); }
The above is the entire content of this article, the way to implement inheritance in JavaScript, thank you all for reading, the editor will continue to work hard!