Recently I'm watching "Javascript Advanced Programming" (Second Edition)
Creation of objects in javascript
• Factory mode
•Constructor mode
•Prototype mode
•Combining constructor and prototype pattern
•Prototype dynamic mode
Most object-oriented languages have the concept of a class, through which multiple objects with the same methods and attributes can be created. Although technically, javascript is an object-oriented language, javascript does not have the concept of classes, everything is an object. Any object is an instance of a certain reference type and is created through existing reference types; the reference type can be native or customized. The native reference types are: Object, Array, Data, RegExp, Function. ! A reference type is a data structure that organizes data and functions together, usually called a class. In JavaScript that lacks the concept of class, the problem that needs to be solved is how to create objects efficiently.
1.1.0. General methods for creating objects
var person = {}; //Object literal representation is equivalent to var person = new Objcect(); person.name = 'evansdiy'; person.age = '22'; person.friends = ['ajiao','tiantian','pangzi']; person.logName = function() { console.log(this.name);}Based on the Object reference type, an object is created, which contains four properties, one of which is a method. If you need many instances like person, there will be a lot of duplicate code.
1.1.1. Factory model
Create an object with a function that can contain the details of the object and then return the object.
function person(name,age,friends) { var o = { name: name, age: age, friends: friends, logName: function() { console.log(this.name); } }; return o;}var person1 = person('Evansdiy','22',['ajiao','tiantian','pangzi']);Every time the person function is called, a new object is created through the object o inside the function, and then returned. Apart from this, this internal object o exists for creating a new object has no other purpose. In addition, it is impossible to determine the type of object created by factory mode.
1.1.2. Constructor mode
function Person(name,age,job) { this.name = name; this.age = age; this.job = job; this.logName = function() { console.log(this.name); }}//Create an instance of Person through the new operator var person1 = new Person('boy-a','22','worker');var person2 = new Person('girl-b','23','teacher');person1.logName(); //boy-aperson2.logName(); //girl-aComparing the factory mode, we can find that there is no need to create intermediate objects here, there is no return. In addition, the instance of the constructor can be identified as a specific type, which solves the problem of object recognition (by checking the constructor attribute of the instance, or using the instanceof operator to check whether the instance is created by a constructor).
console.log(person1.constructor == Person);//constructor is located in the constructor prototype and points to the constructor, and the result is true
console.log(person1 instanceof Person);//Use the instanceof operator to determine whether person1 is an instance of the constructor Person, but the constructor pattern also has its own problems. In fact, the logName method will be recreated once on each instance. It should be noted that the methods created by instantiation are not equal, and the following code will get false:
console.log(person1.logName == person2.logName);//false We can move the method outside the constructor (changed into a global function) to solve this problem:
function logName() { console.log(this.name);}function logAge() { console.log(this.age);}However, global functions created globally can only be called by instances created by Person, which is a bit unrealistic; if there are many methods, they still need to be defined one by one, lacking encapsulation.
1.1.3. Prototype mode
Each function in javascript contains a pointer to the prototype attribute (most browsers can access it through the internal attribute __proto__), a prototype attribute is an object that contains properties and methods shared by all instances created by a certain reference type.
function Person() {}Person.name = 'evansdiy';Person.prototype.friends = ['ajiao','jianjian','pangzi'];Person.prototype.logName = function() { console.log(this.name);}var person1 = new Person();person1.logName();//'evansdiy'The above code does these things:
1. Define a constructor Person. The Person function automatically obtains a prototype property. This property only contains a constructor property pointing to Person by default;
2. Add three attributes through Person.prototype, one of which is used as a method;
3. Create an instance of Person, and then call the logName() method on the instance. !
What you need to note here is the calling process of the logName() method:
1. Look up the logName() method on the person1 instance and found that there is no such method, so I traced back to the prototype of person1
2. Look for the logame() method on the prototype of person1. There is this method. So we call this method based on such a search process. We can prevent the instance from accessing the same-name attribute on the prototype by defining the same-name attribute in the prototype on the instance. It should be noted that doing so will not delete the same-name attribute on the prototype, but will only prevent the instance from accessing.
var person2 = new Person();
person2.name = 'laocai'; If we no longer need properties on the instance, we can delete it through the delete operator.
delete person2.name; use the for-in loop to enumerate all attributes that an instance can access (regardless of whether the attribute exists in the instance or in the prototype):
for(i in person1) { console.log(i);}At the same time, you can also use the hasOwnProperty() method to determine whether a certain property exists on the instance or in the prototype. Only when the property exists in the instance will true be returned:
console.log(person1.hasOwnProperty('name'));//true! hasOwnProperty comes from the prototype of Object and is the only way in javascript to not look up the prototype chain when processing properties. [via javascript secret garden] In addition, you can also use the in operator and hasOwnProperty() method to determine whether a certain property exists in the instance or in the prototype:
console.log(('friends' in person1) && !person1.hasOwnProperty('friends'));First determine whether person1 can access the friends property. If possible, then determine whether this property exists in the instance (note the previous!). If it does not exist in the instance, it means that this property exists in the prototype. As mentioned earlier, the prototype is also an object, so we can write the prototype using object literal representation. The previous writing method of adding code to the prototype can be modified to:
Person.prototype = { name: 'evansdiy', friends: ['ajiao','jianjian','pangzi'], logName: function() { console.log(this.name); }}Since the object literal syntax rewrites the entire prototype prototype, the constructor attribute obtained by default when creating the constructor will point to the Object constructor:
//After the object literal rewrites the prototype
console.log(person1.constructor);//Object However, the instanceof operator will still return the desired result:
//After the object literal rewrites the prototype
console.log(person1 instanceof Person);//true Of course, you can manually set the constructor value in the prototype to solve this problem.
Person.prototype = { constructor: Person, ......}If the prototype object is modified after the object instance is created, the modification of the prototype will be immediately reflected in all object instances:
function Person() {};var person1 = new Person();Person.prototype.name = 'evansdiy';console.log(person1.name);//'evansdiy'The connection between an instance and a prototype is just a pointer, not a copy of the prototype. The prototype is actually a search process. Any modifications made to the prototype object will be reflected in all object instances, even if the prototype is modified after the instance is created. What if the prototype object is rewrite after creating an object instance?
function Person() {};var person1 = new Person1();//The created instance refers to the original prototype//The prototype Person.prototype = { friends: ['ajiao','jianjian','pangzi']}var person2 = new Person();//This instance refers to the new prototype console.log(person2.friends); console.log(person1.friends);The above code will have an undefined error when it is executed to the last line. If we use for-in to enumerate the accessible properties in person1, we will find that there is nothing inside, but person2 can access the friends attribute on the prototype. ! Rewriting the prototype cuts off the connection between the existing prototype and all object instances created before. The prototype of the object instance created before is still there, but it is old.
//When creating person1, the prototype object has not been rewritten yet. Therefore, the constructor in the prototype object is still the default Person()console.log(person1.constructor);//Person()//But the constructor of person2 points to Object()console.log(person2.constructor);//Object()
It should be noted that the prototype pattern ignores the process of passing parameters for the constructor, and all instances obtain the same attribute value. At the same time, there is a big problem with the prototype pattern, that is, the reference type value in the prototype object will be shared by all instances, and the modification of the reference type value will also be reflected in all object instances.
function Person() {};Person.prototype = { friends: ['ajiao','tiantian','pangzi']}var person1 = new Person();var person2 = new Person();person1.friends.push('laocai');console.log(person2.friends);//['ajiao','tiantian','pangzi','laocai']Modifying the reference type value of person1 friends means that the friends in person2 will also change. In fact, the friends saved in the prototype are actually just a pointer to the friends value in the heap (the length of this pointer is fixed and saved on the stack). When an instance accesses the reference type value through the prototype, it is also accessed by pointer instead of accessing the copy on the respective instance (such a copy does not exist).
1.1.4. Create objects in combination with constructor and prototype pattern
Combining the advantages of constructor and prototype mode, making up for their respective shortcomings, using constructors to pass initialization parameters, define instance attributes in them, and using prototypes to define common methods and public attributes. This mode is most widely used.
function Person(name,age) { this.name = name; this.age = age; this.friends = ['ajiao','jianjian','pangzi'];}Person.prototype = { constructor: Person, logName: function() { console.log(this.name); }}var person1 = new Person('evansdiy','22');var person2 = new Person('amy','21');person1.logName();//'evansdiy'person1.friends.push('haixao');console.log(person2.friends.length);//31.1.5. Prototype dynamic mode
The prototype dynamic mode encapsulates all the information required into the constructor, and uses the if statement to determine whether a certain property in the prototype exists. If it does not exist (when the constructor is called for the first time), execute the prototype initialization code inside the if statement.
function Person(name,age) { this.name = name; this.age = age; if(typeof this.logName != 'function') { Person.prototype.logName = function() { console.log(this.name); }; Person.prototype.logAge = function() { console.log(this.age); }; }; };}var person1 = new Person('evansdiy','22');//The constructor was called for the first time, and the prototype was modified at this time. var person2 = new Person('amy','21');//The logName() method already exists and the prototype will not be modified againIt should be noted that this pattern cannot use object literal syntax to write prototype objects (this will override the prototype objects). If the prototype is rewrite, the prototype object accessible to the first instance created by the constructor will not contain the prototype object properties in the if statement.
function Person(name,age) { this.name = name; this.age = age; if(typeof this.logName != 'function') { Person.prototype = { logName: function() { console.log(this.name); }, logAge: function() { console.log(this.Age); } } } };}var person1 = new Person('evansdiy','22');var person2 = new Person('amy','21');person2.logName();//'amy'person1.logName();//logName() method does not existIt should be noted that each model has its own application scenarios, and it doesn’t matter its advantages and disadvantages.
The above analysis of various patterns of creating objects in JavaScript is all the content I share with you. I hope it can give you a reference and I hope you can support Wulin.com more.