Each object in javascript has a built-in property prototype. The explanation of the prototype property of an object in Javascript is: Return a reference to the object type prototype. It means that the prototype attribute holds a reference to another JavaScript object, which acts as the parent of the current object.
The code copy is as follows:
A.prototype = new B();
Understanding prototype should not be confused with inheritance. A's prototype is an instance of B. It can be understood that A cloned all the methods and properties in B. A can use B's methods and properties. What is emphasized here is cloning rather than inheritance. This can happen: A's prototype is an instance of B, and B's prototype is also an instance of A.
Continue to look at the following analysis:
Private variables and functions
If the variables and functions defined inside the function are not provided externally, they cannot be accessed externally, that is, the private variables and functions of the function.
The code copy is as follows:
<script type="text/javascript">
function Box(){
var color = "blue";//Private variable
var fn = function() //Private function
{
}
}
</script>
In this way, the variables color and fn cannot be accessed outside the function object Box, and they become private:
The code copy is as follows:
var obj = new Box();
alert(obj.color);//Undefined pop-up
alert(obj.fn);//Same as above
Static variables and functions
When a function is defined, the attributes and functions added to it are still accessible through the object itself, but their examples cannot be accessed. Such variables and functions are called static variables and static functions respectively.
The code copy is as follows:
<script type="text/javascript">
function Obj(){};
Obj.num = 72;// Static variable
Obj.fn = function() // Static function
{
}
alert(Obj.num);//72
alert(typeof Obj.fn)//function
var t = new Obj();
alert(t.name);//undefined
alert(typeof t.fn);//undefined
</script>
Instance variables and functions
In object-oriented programming, in addition to some library functions, we still hope to define some properties and methods at the same time when object definition, so that they can be accessed after instantiation, and js can also do this.
The code copy is as follows:
<script type="text/javascript">
function Box(){
this.a=[]; //Instance variable
this.fn=function(){ //Instance method
}
}
console.log(typeof Box.a); //undefined
console.log(typeof Box.fn); //undefined
var box=new Box();
console.log(typeof box.a); //object
console.log(typeof box.fn); //function
</script>
Add new methods and properties to instance variables and methods
The code copy is as follows:
<script type="text/javascript">
function Box(){
this.a=[]; //Instance variable
this.fn=function(){ //Instance method
}
}
var box1=new Box();
box1.a.push(1);
box1.fn={};
console.log(box1.a); //[1]
console.log(typeof box1.fn); //object
var box2=new Box();
console.log(box2.a); //[]
console.log(typeof box2.fn); //function
</script>
A and fn were modified in box1, but not in box2. Since arrays and functions are objects and are reference types, this means that although the properties and methods in box1 are the same as those in box2, they are not a reference, but a copy of the properties and methods defined by the Box object.
This has no problem with properties, but it is a big problem for methods, because methods are doing exactly the same function, but there are two copies. If a function object has thousands and instance methods, then each instance of it must maintain a copy of thousands of methods. This is obviously unscientific. What can I do? Prototype came into being.
Basic concepts
Each function we create has a prototype property, which is a pointer to an object, and its purpose is to contain properties and methods that can be shared by all instances of a specific type. Then, prototype is the prototype object of the object instance created by calling the constructor.
The advantage of using a prototype is that it allows an object instance to share the properties and methods it contains. That is, instead of adding definition object information to the constructor, you can directly add this information to the prototype. The main problem with using constructors is that each method needs to be created once in each instance.
In JavaScript, there are two types of values, original values and object values. Each object has an internal property prototype, which we usually call a prototype. The value of the prototype can be an object or null. If its value is an object, the object must also have its own prototype. This forms a linear chain, which we call the prototype chain.
meaning
Functions can be used as constructors. In addition, only the function has a prototype attribute and can be accessed, but the object instance does not have this attribute, there is only an internal inaccessible __proto__ attribute. __proto__ is a mysterious link in the object to the relevant prototype. According to the standard, __proto__ is not disclosed to the public, which means it is a private property, but Firefox's engine exposed it and became a common property, which we can access and set.
The code copy is as follows:
<script type="text/javascript">
var Browser = function(){};
Browser.prototype.run = function(){
alert("I'm Gecko,a kernel of firefox");
}
var Bro = new Browser();
Bro.run();
</script>
When we call the Bro.run() method, since there is no such method in Bro, he will search for it in his __proto__, that is, Browser.prototype, so the run() method is finally executed. (Here, the capitalized letter of the function represents the constructor to distinguish ordinary functions)
When calling the constructor to create an instance, the instance will contain an internal pointer (__proto__) pointing to the constructor's prototype. This connection exists between the instance and the constructor's prototype, not between the instance and the constructor.
The code copy is as follows:
<script type="text/javascript">
function Person(name){ //Constructor function
this.name=name;
}
Person.prototype.printName=function() //Prototype object
{
alert(this.name);
}
var person1=new Person('Byron');//Instantiate the object
console.log(person1.__proto__);//Person
console.log(person1.constructor);//Try it yourself to see what it will be
console.log(Person.prototype);//Point to the prototype object Person
var person2=new Person('Frank');
</script>
Person's instance person1 contains the name attribute, and it automatically generates a __proto__ attribute, which points to Person's prototype, and you can access the printName method defined in the prototype, which is probably like this:
Each JavaScript function has a prototype attribute, which refers to an object, which is the prototype object. The prototype object is empty when initializing. We can customize any properties and methods in it. These methods and properties will be inherited by the objects created by the constructor.
So, now the problem is. What is the relationship between constructor, instance and prototype object?
The difference between constructors, instances and prototype objects
An instance is created through a constructor. Once an instance is created, it has the constructor attribute (pointing to the constructor function) and the __proto__ attribute (pointing to the prototype object).
There is a prototype property in the constructor, which is a pointer to its prototype object.
There is also a pointer (constructor property) inside the prototype object pointing to the constructor: Person.prototype.constructor = Person;
Instances can access properties and methods defined on the prototype object.
Here person1 and person2 are instances, and prototype are their prototype objects.
Another chestnut:
The code copy is as follows:
<script type="text/javascript">
function Animal(name) //Accumulate constructor
{
this.name = name;//Set object properties
}
Animal.prototype.behavior = function() //Add behavior method to the prototype of the base class constructor
{
alert("this is a "+this.name);
}
var Dog = new Animal("dog");//Create Dog object
var Cat = new Animal("cat");//Create Cat object
Dog.behavior();//Call the behavior method directly through the Dog object
Cat.behavior();//output "this is a cat"
alert(Dog.behavior==Cat.behavior);//output true;
</script>
It can be seen from the program running results that the methods defined on the prototype of the constructor can indeed be called directly through the object, and the code is shared. (You can try to remove the prototype property in Animal.prototype.behavior to see if it can still run.) Here, the prototype property points to the Animal object.
Array object instance
Let's look at an instance of the array object. When we create the object array1, the actual object model of array1 in the Javascript engine is as follows:
The code copy is as follows:
var array1 = [1,2,3];
The array1 object has a length attribute value of 3, but we can add elements to array1 by the following method:
The code copy is as follows:
array1.push(4);
The push method comes from a method that points to the object by the __proto__ member of array1 (Array.prototye.push()). It is precisely because all array objects (created through []) contain a __proto__ member pointing to the same method object with push, reverse, etc. (Array.prototype), that these array objects can use push, reverse and other methods.
Function object instance
The code copy is as follows:
function Base() {
this.id = "base"
}
The code copy is as follows:
var obj = new Base();
What is the result of such code? The object model we see in the Javascript engine is:
What exactly did the new operator do? In fact, it was very simple, just did three things.
The code copy is as follows:
var obj = {};
obj.__proto__ = Base.prototype;
Base.call(obj);
Prototype chain
Prototype chain: When a property or method is retrieved from an object, if the object itself does not have such a property or method, it will search for the prototype object you associate with. If there is no prototype, it will search for the predecessor of prototype associated with prototype. If there is no more, continue to search for the object referenced by Prototype.Prototype, and so on until Prototype.......Prototype is undefined (Object's Prototype is undefined), thus forming the so-called "prototype chain".
The code copy is as follows:
<script type="text/javascript">
function Shape(){
this.name = "shape";
this.toString = function(){
return this.name;
}
}
function TwoShape(){
this.name = "2 shape";
}
function Triangle(side,height){
this.name = "Triangle";
this.side = side;
this.height = height;
this.getArea = function(){
return this.side*this.height/2;
}
}
TwoShape.prototype = new Shape();
Triangle.prototype = new TwoShape();
</script>
Here, a new entity is created with the constructor Shape(), and then it is used to overwrite the prototype of the object.
The code copy is as follows:
<script type="text/javascript">
function Shape(){
this.name = "shape";
this.toString = function(){
return this.name;
}
}
function TwoShape(){
this.name = "2 shape";
}
function Triangle(side,height){
this.name = "Triangle";
this.side = side;
this.height = height;
this.getArea = function(){
return this.side*this.height/2;
}
}
TwoShape.prototype = new Shape();
Triangle.prototype = new TwoShape();
TwoShape.prototype.constructor = TwoShape;
Triangle.prototype.constructor = Triangle;
var my = new Triangle(5,10);
my.getArea();
my.toString();//Triangle
my.constructor;//Triangle(side,height)
</script>
Prototype inheritance
Prototype inheritance: At the end of the prototype chain, it is the prototype object pointed to by the Object constructor prototype attribute. This prototype object is the ancestor of all objects, and this ancestor implemented methods that all objects such as toString should have innately. Other built-in constructors, such as Function, Boolean, String, Date and RegExp, are inherited from this ancestor, but they each define their own attributes and methods, so that their descendants show the characteristics of their respective clans.
In ECMAScript, the method of implementing inheritance is achieved by relying on the prototype chain.
The code copy is as follows:
<script type="text/javascript">
function Box(){ //The inherited function is called supertype (parent class, base class)
this.name = "Jack";
}
function Tree(){ //Inherited functions are called subtypes (subclasses, derived classes)
this.age = 300;
}
//Inherit through prototype chain, assign the prototype attributes of the subtype
//new Box() will hand over the information in the box construct and the information in the prototype to Tree
Tree.prototype = new Box();//Tree inherits Box and forms a chain through the prototype.
var tree = new Tree();
alert(tree.name);//Popt Jack
</script>
Problem with prototype chain: Although the prototype chain is very powerful and can be used to implement inheritance, it also has some problems. The most important problem comes from the value prototype containing the reference type. Prototype attributes containing reference types are shared by all instances; this is why attributes are defined in constructors, not in prototype objects. When inheritance is achieved through a prototype, the prototype actually becomes an instance of another type. Therefore, the original instance attribute becomes the prototype attribute.
When creating an instance of a subtype, the argument cannot be passed to the supertype constructor. In fact, it should be said that there is no way to pass parameters to the supertype constructor without affecting all object instances. In addition to the problem that just discussed due to the inclusion of reference type values in prototypes, it is rare to use prototype chains alone in practice.
Another chestnut:
The code copy is as follows:
<script type="text/javascript">
function Person(name)
{
this.name = name;//Set object properties
};
Person.prototype.company = "Microsoft";//Set the properties of the prototype
Person.prototype.SayHello = function() //Prototype method
{
alert("Hello,I'm "+ this.name+ " of " + this.company);
};
var BillGates = new Person("BillGates");//Create person object
BillGates.SayHello();//Inherits the content of the prototype and outputs "Hello,I'm BillGates of Microsoft"
var Jobs = new Person("Jobs");
Jobs.company = "Apple";//Set your own company attribute to cover up the prototype's company attribute
Jobs.SayHello = function()
{
alert("Hi,"+this.name + " like " + this.company);
};
Jobs.SayHello();//The properties and methods you override themselves, output "Hi,Jobs like Apple"
BillGates.SayHello();//The coverage of Jobs does not affect the prototype, BillGates still outputs
</script>
See the following example of the prototype chain:
The code copy is as follows:
<script type="text/javascript">
function Year(){
this.value = 21;
}
Year.prototype = {
method:function(){
}
};
function Hi(){
};
//Set Hi's prototype property to the instance object of Year
Hi.prototype = new Year();
Hi.prototype.year = 'Hello World';
Hi.prototype.constructor = Hi;
var test = new Hi();//Create a new instance of Hi
//Prototype chain
test [Hi example]
Hi.prototype [Example of Year]
{year:'Hello World'}
Year.prototype
{method:…};
object.prototype
{toString:...};
</script>
From the above example, the test object is inherited from Hi.prototype and Year.prototype; therefore it can access Year's prototype method method, and at the same time it can access the instance property value
__ptoto__ attribute
The __ptoto__ attribute (not supported by IE browser) is a pointer to the prototype object of the instance. Its function is to point to the prototype attribute constructor of the constructor. Through these two attributes, you can access the properties and methods in the prototype.
An object instance in Javascript is essentially composed of a series of properties. Among these properties, there is an internally invisible special property - __proto__. The value of this property points to the prototype of the object instance. An object instance only has a unique prototype.
The code copy is as follows:
<script type="text/javascript">
function Box(){ //Uppercase, representing the constructor
Box.prototype.name = "trigkit4";//Prototype attributes
Box.prototype.age = "21";
Box.prototype.run = function()//Prototype method
{
return this.name + this.age + 'studying';
}
}
var box1 = new Box();
var box2 = new Box();
alert(box1.constructor);//Construct the attribute, you can get the constructor itself,
//The function is to be positioned by the prototype pointer and then obtain the constructor itself
</script>
The difference between __proto__ attribute and prototype attribute
prototype is a proprietary property in function object.
__proto__ is an implicit property of a normal object. When new, it will point to the object pointed to by prototype;
__ptoto__ is actually an attribute of a certain entity object, while prototype is an attribute belonging to the constructor. __ptoto__ can only be used in learning or debugging environments.
Prototype mode execution process
1. First look for the attributes or methods in the constructor instance, and if so, return immediately.
2. If there is no instance of the constructor, go to its prototype object and return immediately.
Prototype object
The code copy is as follows:
<script type="text/javascript">
function Box(){ //Uppercase, representing the constructor
Box.prototype.name = "trigkit4";//Prototype attributes
Box.prototype.age = "21";
Box.prototype.run = function()//Prototype method
{
return this.name + this.age + 'studying';
}
}
var box1 = new Box();
alert(box1.name);//trigkit4, the value in the prototype
box1.name = "Lee";
alert(box1.name);//Lee, go to the principle
var box2 = new Box();
alert(box2.name);//trigkit4, the value of the prototype, not modified by box1
</script>
The constructor's
The code copy is as follows:
<script type="text/javascript">
function Box(){
this.name = "Bill";
}
Box.prototype.name = "trigkit4";//Prototype attributes
Box.prototype.age = "21";
Box.prototype.run = function()//Prototype method
{
return this.name + this.age + 'studying';
}
var box1 = new Box();
alert(box1.name);//Bill, the value in the prototype
box1.name = "Lee";
alert(box1.name);//Lee, go to the principle
</script>
To sum up, let’s sort it out:
The code copy is as follows:
<script type="text/javascript">
function Person(){};
Person.prototype.name = "trigkit4";
Person.prototype.say = function(){
alert("Hi");
}
var p1 = new Person();//prototype is a prototype object of p1 and p2
var p2 = new Person();//p2 is an instantiated object, and there is a __proto__ attribute inside it, pointing to Person's prototype
console.log(p1.prototype);//undefined, this property is an object and cannot be accessed
console.log(Person.prototype);//Person
console.log(Person.prototype.constructor);//There is also a pointer (constructor property) inside the prototype object pointing to the constructor function
console.log(p1.__proto__);//This property is a pointer pointing to the prototype object of prototype
p1.say();//Instances can access properties and methods defined on the prototype object
</script>
Factory model
The code copy is as follows:
function createObject(name,age){
var obj = new Object();
obj.name = name;
obj.age = age;
return obj;
}
The factory pattern solves the problem of large-scale duplication of instantiated objects, but there is another problem, that is, it is impossible to figure out which instance of the object they are.
Using the constructor method not only solves the problem of repeated instantiation, but also solves the problem of object recognition.
The difference between using constructor methods and factory patterns is that:
1. Create object (new Object()) that is not displayed by the constructor method;
2. Directly assign attributes and methods to this object
3. No return statement
When the constructor is used and the new constructor() is used, new Object() is executed in the background;
This in the function body represents the object derived from new Object()
1. Determine whether the property is in the constructor instance or in the prototype, you can use the `hasOwnProperty()` function
2. The way to create literals is used to create constructor attributes will not point to the instance, but to the Object, and the way to create constructors is the opposite.
Why point to Object? Because Box.prototype = {};This way of writing is actually to create a new object.
Every time a function is created, its prototype will be created at the same time, and this object will automatically obtain the constructor attribute
3. If it is an instance method, different instantiation, their method addresses are different and unique.
4. If it is a prototype method, then their address is shared