Introduction of prototype
function Person(name, age, gender) { this.name = name; this.age = age; this.gender = gender; //Add a method to the object this.sayName = function () { console.log("I am" + this.name); } } //Create an instance of Person var per = new Person("Sun WuKong", 18, "male"); var per2 = new Person("Zhu Bajie", 28, "male"); per.sayName(); per2.sayName(); console.log(per.sayName == per2.sayName); //The print result is false
The analysis is as follows:
In the above code, our sayName method is written inside the constructor Person, and then called in two instances. As a result, each time the constructor executes, a new sayName method is created for each instance. That is, the sayName of each instance is unique. Therefore, the print result of the last line of code is false.
According to the above method, if 10000 object instances are created, 10000 sayName methods will be created. This kind of writing is certainly inappropriate. Why don't we let all objects share the same method?
Another way is to define the sayName method in the global scope: (not recommended. See the note for the reason)
function Person(name, age, gender) { this.name = name; this.age = age; this.gender = gender; //Add a method to the object this.sayName = fun; } //Define the sayName method in the global scope /* * Defining functions in the global scope pollutes the namespace of the global scope * Moreover, the definition is not safe in the global scope */ function fun() { alert("Hello Hello, I'm:" + this.name); };
A better way is to add the sayName method to the prototype:
Person.prototype.sayName = function(){ alert("Hello Hello, I'm:"+this.name); };
This introduces the "prototype" we want to talk about in this article.
Concept of prototype
Understanding 1:
For each function we create, the parser will add an attribute prototype to the function. This attribute corresponds to an object, which is what we call the prototype object.
If a function calls prototype as an ordinary function, it has no effect. When a function is called in the form of a constructor, the instance object it creates will have an implicit attribute pointing to the prototype of the constructor. We can__ proto__ To access the property.
Code example:
// Define constructor function Person() {} var per1 = new Person(); var per2 = new Person(); console.log(Person.prototype); // Print result: [object] console.log(per1.__proto__ == Person.prototype); // Print result: true
The last line of the code above: the print result shows that the instance__ proto__ And constructor. Prototype refer to prototype objects.
Awareness 2:
The prototype object is equivalent to a public area. All instances of the same class can access the prototype object. We can uniformly set the common contents of the object into the prototype object.
When we create constructors in the future, we can uniformly add the properties and methods shared by these objects to the prototype object of the constructor, so that each object can have these properties and methods without adding them separately for each object and affecting the global scope.
Understanding 3:
When using in to check whether an object contains a property, if it does not exist in the object but exists in the prototype, it will also return true.
You can use the object's hasOwnProperty() to check whether the object itself contains the property.
Prototype chain
The prototype object is also an object, so it also has a prototype. When we use or access the properties or methods of an object:
-
It will first look in the object itself and use it directly if it exists;
-
If not, it will be searched in the prototype object. If it is found, it will be used directly;
-
If not, search the prototype of the prototype until the prototype of the Object object is found.
-
The prototype of the Object object does not have a prototype. If it is still not found in the Object prototype, null is returned
summary
It is difficult to understand when you first contact the "prototype" and "prototype chain". Contact more times, and then look back, you will gradually get familiar with it.
Object's toString() method
Let's look at the following code first:
function Person(name, age, gender) { this.name = name; this.age = age; this.gender = gender; } var per1 = new Person("vae", 26, "male"); console.log("per1 = " + per1); console.log("per1 = " + per1.toString());
Print results:
per1 = [object Object] per1 = [object Object]
In the above code, we tried to print the internal information of the instance per1, but found that whether printing per1 or per1.toString(), the result is object. Why? The analysis is as follows:
-
When we print an object directly on the page, we actually output the return value of the toString() method of the object.
-
If we want to print an object without outputting [object Object], we can manually add a toString() method for the object. This means that you override the toString() method.
Override the toString() method as follows:
function Person(name, age, gender) { this.name = name; this.age = age; this.gender = gender; } //Method 1: rewrite the toString method of the Person prototype. Effective for all instances of Person Person.prototype.toString = function() { return ( "Person[name=" + this.name + ",age=" + this.age + ",gender=" + this.gender + "]" ); }; // Method 2: only rewrite the toString method of instance per1. But this way of writing only works for per1, not for per2 /* per1.toString = function() { return ( "Person[name=" + this.name + ",age=" + this.age + ",gender=" + this.gender + "]" ); }; */ var per1 = new Person("smyh", 26, "male"); var per2 = new Person("vae", 30, "male"); console.log("per1 = " + per1); console.log("per2 = " + per2.toString());
Print results:
per1 = Person[name=smyh,age=26,gender=male] per2 = Person[name=vae,age=30,gender=male]
Code analysis:
In the code above, take a closer look at the comments. We have rewritten the toString() of the Person prototype, so that all instances of Person can be guaranteed to take effect.
From this example, we can see the role of prototype.
Garbage collection (GC) mechanism of JS
Garbage will be generated during the running of the program. After these garbage are accumulated too much, the running speed of the program will be too slow. Therefore, we need a garbage collection mechanism to deal with the garbage generated during the operation of the program.
When an object does not have any variables or attributes to reference it, we will never be able to operate the object. At this time, this object is garbage. Too many objects will occupy a lot of memory space and slow down the program, so this garbage must be cleaned up.
The above sentence can also be understood as follows: if there is no variable pointing to the object in the heap memory, the object in the heap memory will become garbage.
JS has an automatic garbage collection mechanism, which will automatically destroy these garbage objects from memory. We don't need and can't do garbage collection. All we need to do is: if you no longer use the object, set the reference of the changed object to null.