This article introduces several methods of creating objects in js and shares them with you for your reference. The specific content is as follows
1. Factory mode
Disadvantages: It does not solve the problem of object recognition, that is, how to know the type of an object.
2. Constructor pattern
Compared with factory mode:
1. No explicit object creation
2. Directly assign properties and methods to this object
3. No return statement
To create an instance of person, you must use the new operator. Calling the constructor in this way actually goes through 4 steps:
1. Create a new object
2. Assign the scope of the constructor to the new object
3. Execute the code in the constructor
4. Return new object
Create a custom constructor to identify its instance as a specific type.
Constructor Disadvantages:
Each method is recreated on each instance. Both person1 and person2 have a sayName() method, but the two methods are not the same Function instance. Functions with the same name on different instances are not equal.
There is no need to create two Function instances that complete the same task, and there is still this object. There is no need to bind the function to a specific object before executing the code, as shown below.
Set the sayName attribute to the global sayName function. In this way, since sayName contains a pointer to a function, the person1 and person2 objects share the same function.
However, if the object needs to define many methods, then many global functions must be defined, and there is no encapsulation of custom reference types. In order to solve the above problems, the prototype mode is introduced.
3. Prototype mode
Understanding prototype objects
Every function we create has a prototype attribute, which is a pointer to an object, and the purpose of this object is to contain properties and methods that can be shared by all instances of a specific type. Prototype is the object prototype of the object instance created by calling the constructor. The advantage of using a prototype object is that all object instances can share the properties and methods it contains.
First, the parser will ask the instance person1 whether it has a name attribute, and if so, it will return it.
If not, continue to search for the name attribute in the prototype of person1, and return if there is one.
If not, continue searching in the prototype of person1's prototype.
isPrototypeOf() determines the association between the instance and the prototype object
console.log(Person.prototype.isPrototypeOf(person1)); //true
Object.getPrototypeOf() returns the value of [[prototype]]
console.log(Object.getPrototypeOf(person1));
//Person {name: “Yvette”, age: 26, job: “engineer”} returns the prototype object of Person.
console.log(Object.getPrototypeOf(person1) === Person.prototype)//true
console.log(Object.getPrototypeOf(person1).name);//"Yvette"
The hasOwnProperty() method can detect whether a property exists in the instance or in the prototype. It will return true only if the given property exists in the instance.
console.log(person1.hasOwnProperty(“name”));//false
Prototype and in operator
There are two ways to use the in operator: alone and within a for-in loop. When used alone, the in operator returns true if the given property is accessible through the object, whether the property resides in the instance or the prototype.
Using a for in loop, all enumerable properties that can be accessed through the object are returned, including properties in the instance and properties that exist in the prototype. This will also be returned if a property in the instance masks a non-enumerable property in the prototype. There is a bug in the implementation of versions before IE9. Instance attributes that mask non-enumerable attributes will not be returned in for-in.
There is no log information in the button before IE9. Although the toString() method in the person instance blocks the non-enumerable toString() in the prototype;
Prototype abbreviation
This causes person1.constructor to no longer point to Person, but to Object. If the constructor is important, you need to specifically set it to an appropriate value, such as:
But this approach will cause the constructor property to become enumerable.
If you want to set it to be non-enumerable (the default is not enumerable), you can use Object.defineProperty(Person.prototype, “constructor”, {
enumerable: false,
value: Person
});
Dynamic nature of prototype
Since the process of finding a value in the prototype is a search, any changes we make to the prototype object are immediately reflected on the instance.
The situation is different if the entire prototype object is overridden. When the constructor is called, a [[prototype]] pointer to the original prototype is added to the instance, and modifying the prototype to another object is equivalent to cutting off the connection between the constructor and the original prototype. The pointer in the instance only points to the prototype, not the constructor.
person.prototype points to the original prototype object and does not point to the new prototype object.
Problems with prototype objects
The biggest problem with the prototype pattern is caused by its shared nature.
The problem is more prominent for properties containing reference type values
The original intention was to modify person1’s friends, but it caused the value of person2’s friends attribute to also change. Therefore we rarely use the prototype pattern alone.
4. Combine construction mode and prototype mode
The most common way to create custom types is to use a combination of constructor pattern and prototype pattern. The constructor pattern is used to define instance properties, and the prototype pattern is used to define methods and shared properties. In this way, each instance has its own copy of the instance properties and shares references to methods, which saves memory to the greatest extent. .
In addition to the above methods, there are also dynamic prototype mode, parasitic construction mode and solid construction mode, but due to the low frequency of use, I will not go into details.