JavaScript does not support inherited patterns of traditional classes, it is a prototype-based inheritance, that is, through prototype settings to implement inheritance
Let's consider the following question
function person () { this . Name = "haha" ; this . Sayname = function () {Console.log ( this .name); }} var p1 = new
person ();
var p2 =
new
person (); P1.sayname (); Console.log (p1.sayname = = = P2.sayname);
//
false
When we use the constructor pattern (called by new function), we find that the methods within the constructor are created once in each instance, that is, to implement the same function to create two functions (the function is also an object, that is, when we create more instances, To inevitably create more objects of the same function, this does not conform to the idea of multiplexing)
To implement the problem of referencing a function (object) We can move the Sayname method above to the outside of the person construct and bind to a specific object when instantiated through this, which implements the same function (object) of different object references
function person () {this.name = "haha"; this.sayname = Sayname;} function Sayname () {console.log (this.name);} var p1 = new Person (), var p2 = new Person ();p 1.sayName ()//hahaconsole.log (p1.sayname = = = P2.sayname);//true
The way to solve the problem is also a big problem, that is 1) the function of the global role is only called by an object, it should be considered that the global function location is somewhat unreasonable (position a bit large) 2) when we want to define a lot of similar functions for person, Then this person does not exist what we call encapsulation, most of the methods it defines are exposed outside
And that leads to the prototype pattern.
Prototypes: Each function has a prototype (prototype) attribute, which is a pointer to an object that contains properties and methods that can be shared by all instances of a particular type, that is, prototype is the prototype object for which you created the instance.
Prototype mode
Here's a simple example.
var animal = function () {This.type = "animal"; this.testtype = "Haha";} Animal.prototype.sayType = function () {console.log (this.type);};/ /Add a method to the animal prototype
var person = function () {this.type = ' person ';//Adds a new type in person, masks type}//in animal to add a property to person Person.prototype = new Animal ();//Set the prototype of person to point to (the same) Animal instance var a = new person (); A.saytype (); Console.log (A.testtype);
A[person instance]
{type: ' person '}
Person.prototype[animal instance]
{type: "Animal" Testtype: "Haah"}
Animal.prototype
{Function:saytype}
object.prototype//Default Prototypes
{}
A prototype of a object is an instance of animal, so a can access a property or method in a animal instance, and through an instance of animal accesses a property or method in a animal prototype, we can access the value saved in the prototype through an object instance. However, the value of the prototype cannot be overridden by an object instance, and if we add a property or method in the instance to the prototype, we create the property or method in this instance that masks the property or method in the prototype.
This is because the process of property lookup is looked up from the beginning of the instance along the prototype chain, and when the corresponding property is found, it returns if Object.prototype is found, and returns undefined
So when we just want to get the attributes from the instance, rather than get the properties from the prototype, we're going to pass the hasOwnProperty () method.
Disadvantage: The above mode of pointing the prototype attribute of an instance to another instance causes all properties in the prototype to be shared by the instance (pointing to the same instance) and we cannot pass parameters to the prototype (which will also cause problems of all instances of the same property) When the attribute of a reference type is present in this instance, it is possible to have unexpected results.
function Supertype () { Span style= "color: #0000ff;" >this . Colors = ["Red", "green" function subtype () {} Su Btype.prototype = new supertype (); var a = new subtype (); var b = new subtype (); A.colors.push ( black "); Console.log (b.colors);//red Green Black
Console.log (a instanceof subtype);//true
Console.log (a instanceof supertype);//true
Console.log (a instanceof Object);//true reflects the relationship between the instance and the prototype due to the relationship of the prototype chain, it can be said that a instance is an instance of the type appearing in the prototype chain.
The above example shows that when a prototype has a reference type in the object, modifying the value in one instance will also be affected (because the attribute is found in the prototype chain and does not exist in its own instance, so it will produce such a result)
Based on the above reasons, we seldom use a single prototype chain to implement inheritance ( the implementation mechanism of inheritance is to rewrite the prototype object )
In order to solve the problem of reference type in super-class prototype, the idea of using a schema (classic inheritance) to borrow a constructor is to call a super-type constructor in the context of a subtype, so that each subtype has its own copy of a super-type. It also has the advantage of passing arguments to a super-type constructor (that is, implementing a definition of a different subtype)
functionsupertype (name) { This. Name =name; This. colors = ["Red", "green"]; } functionsubtype (name) {Supertype.call ( This, name); //You can add your own properties or methods here. //the difference between call apply is that the form of the Apply pass parameter must be an array call that is passed in the form of multiple arguments } varA =NewSubtype ("Haha"); varb =NewSubtype ("Hao"); Console.log (a.name);//hahaConsole.log (B.name);//HaoA.colors.push ("Black"); Console.log (a.colors);//["Red", "green", "black"]Console.log (b.colors);//["Red", "green"]
But there are some problems with the use of the constructor pattern. 1) Define a method in a constructor, there is a problem with multiplexing 2) methods defined in a super-type prototype are not visible to the child type
function () { console.log ("HI"); }
When we call the Sayhi method through a generated instance of a, we will report sayhi undefined (because we do not inherit through prototype, so we cannot access the Supertype property through the prototype chain)
This puts forward another pattern, that is, combinatorial inheritance (pseudo-classical inheritance), which is a pattern of combining borrowed and prototype chain technology, that is, to inherit the attribute by borrowing the construction pattern, and the prototype chain to inherit the properties and methods of the prototype.
functionsupertype (name) { This. Name =name; This. colors = ["Red", "green"]; } SuperType.prototype.sayName=function() {Console.log ( This. Name); } functionsubtype (name) {Supertype.call ( This, name); } Subtype.prototype=Newsupertype (); varA =NewSubtype ("Haha"); varb =NewSupertype ("Hao"); A.sayname ();//hahaB.sayname ();//HaoA.colors.push ("Black"); Console.log (a.colors);//["Red", "green", "black"]Console.log (b.colors);//["Red", "green",]
In such a pattern, an instance has a copy of its own prototype property, and it is also the most common inherited pattern to access the properties inherited from the prototype through the prototype chain.
Reference JavaScript Advanced Programming
Uncle Tom's Blog powerful prototype and prototype chain: http://www.cnblogs.com/TomXu/archive/2012/01/05/2305453.html
Prototype and prototype inheritance