Object-Oriented Programming-fundamentals (factory, constructor, prototype, hybrid, dynamic, etc.)

Source: Internet
Author: User
Tags hasownproperty

This article refers to: JS Advanced Programming Third Edition
This article I ate most of the days written, is very annoying, no perseverance to see the doomed or not

(1), Factory mode:
Encapsulates a function Createperson, which creates a human object, contains three attributes and a method, and then uses this function to create 2 object P1,P2 respectively.

functionCreateperson (name,age,job) {varp=NewObject (); P.name=name; P.age=Age ; P.job=job; P.showname=function() {alert ( This. Name);                        }; returnp;}varP1=createperson (' jxj1 ', ' student '); varP2=createperson (' jxj2 ', +, ' teacher ');

Factory mode solves the problem of creating multiple similar objects, but does not solve the object recognition problem (the type of the object is not known to be an array or a function or a regular, etc.)
Alert (P1 instanceof Object); True
Alert (P1 instanceof Createperson); False
Alert (P2 instanceof Object); True
Alert (P2 instanceof Createperson); False

(2), constructor mode
Create a constructor that is accustomed to the initial capitalization of the constructor, the first letter of the non-constructor is lowercase, and also contains three attributes and a method, and then uses this function to create 2 instance object P1,p2, respectively. (a constructor can also be used as a normal function, which is used as a constructor only if it is called with new)
Let's start with the constructor from the write function in Factory mode above

functionPerson (name,age,job) { This. name=name;  This. age=Age ;  This. job=job;  This. showname=fucntion () {alert ( This. Name);                };                }; varp1=NewPerson (' jxj1 ', ' student '); varP2=NewPerson (' jxj2 ', ' teacher ');


This example of the constructor replaces the previous normal function, what is the difference between the two?
Relative Factory mode constructor
1, there is no explicitly created object, that is, there is no var p=new object in the function ();
2, Directly the properties and methods are paid directly to the This object (the friend who understands this is aware that this is a pointer to the Global object window when there is no new object);
3, no return statement
interprets this in the constructor again. The function of the constructor is to create the object, here we have new two objects P1, p2, and then call P1 and P2 this point to itself, rather than window (do not understand the scope of this)
P1 and P2 are different instances of person, All two objects have an attribute constructor (the property of the constructor), which points to the person's constructor,
Alert (P1.constructor==person),//true
Alert ( P2.constructor==person); True

Well, the reason why the constructor is introduced, does not say its advantages, the previous said that the factory method can not solve the object recognition problem, then the constructor will be able to identify the
alert (P1 instanceof object);//true
Alert (P1 instanceof person); True
Alert (P2 instanceof Object);//true
Alert (p2 instanceof person);//true
actually said so much, the constructor is still imperfect, flawed, Have you noticed that there is a ShowName method in the constructor, the method has a function, and the problem is that
P1,p2 is the two different instances of person, The ShowName methods in P1 and P2 are not the same (different instances of the same name function are not equal)
alert (p1.showname = = p2.showname);//false
in other words, The constructors for each instantiation are as follows (just to understand, not to write)

function Person (name,age,job) {                        this. name=name;                          this. age= age;                         this. job=job;                         this. showname=new  fucntion () {                                alert (this. name);};                

In summary, each instantiation produces a new method, which is the disadvantage

All right, find a way to solve it:

function Person (name,age,job) {            this. name=name;              this. age= age;             this. job=job;             this. showname=showname;        };        Fucntion ShowName () {                alert (this. Name);            };         var p1=New Creatperson (' jxj1 ', ' Student ');         var p2=New Creatperson (' jxj2 ', +, ' teacher ');

In this example, we transfer the definition of the ShowName () function to the outside of the constructor. Inside the constructor, we set the Sayname property equal to the global sayname function. This way, because Sayname contains a pointer to a function
Pointers, so the P1 and P2 objects share the same sayname () function defined in the global scope. This does solve the problem of two functions do the same thing, but ShowName is a global function, if the constructor has a lot of methods, it will not be crazy ah, then this solution can be solved, but not good, well, continue to find ways

(3), prototype
Each function we create has a prototype (prototype) attribute, which is a pointer to an object .... The next step is not to explain the meaning, because it is not easy to understand, for example:

functionPerson (name,age,job) { This. Prototype.name= ' Jxj1 ';  This. prototype.age=24;  This. prototype.job= ' Student ';  This. prototype.showname=fucntion () {alert ( This. Name);        };        }; varp1=NewPerson (); P1.showname ();//jxj1        varP2=NewPerson (); P2.showname ();//jxj1alert (p1.showname==p2.showname);//true

Through the code above, there is no sense that the factory mode and the shortcomings of the constructor mode, will not appear here Ah, this is the strength of the prototype, OK, then we understand what the prototype is


Just say the concept is too abstract, to the illustration.
We use the prototype-written constructor to add all the properties and methods to the prototype property of the person, where the constructor becomes an empty function. Even so, you can still create a new object by calling the constructor, and the new object will also have the same genus
Sex and methods. But unlike the constructor pattern, these properties and methods of the new object are shared by (let) all instances. In other words, p1 and P2 access both the same set of properties and the same sayname () function.
Look at the picture .....
As soon as a new function (person) is created, a prototype property is created for the function, which points to the line prototype object (person Protype), and the prototype object obtains a property constructor. This property points to the function pointer that contains the prototype property. When the constructor is called to create a new instance (Person1,person2), the instance will contain a pointer [[prototype]] inside. The prototype object that points to the constructor. As you can see, Person1 and Person2 are not directly related to constructors, they operate on the object prototype (person Protype) of the constructor function. Keep in mind that the pointer in the instance points only to the prototype, not to the constructor.
Look at the following two sentences:
Alert (Person.prototype.isPrototypeOf (Person1)); True
Alert (Person.prototype.isPrototypeOf (Person2)); True
These 2 sentences indicate that both Person1 and Person2 have a pointer [[prototype]] pointing to the prototype object (Person.prototype).
A new Method object.getprototypeof () is added to the ECMASCRIPT5, which returns the pointer value in the instance object (Person1,person2)
Alert (object.getprototypeof (person1) = = Person.prototype); True
Alert (object.getprototypeof (person1). Name); "Nicholas"

The following is a book on the properties and methods of the prototype access process is still very easy to understand, so I copy:
Each time the code reads a property of an object, the search is performed once, and the target is a property with the given name. The search begins first from the object instance itself. If a property with the given name is found in the instance, the value of the property is returned, and if it is not found, the prototype object that the pointer points to is searched, and the property with the given name is looked up in the prototype object. If this property is found in the prototype object, the value of the property is returned.
In other words, when we call Person1.sayname (), we perform two searches successively. First, the parser asks: "Does the instance Person1 have a sayname attribute?" "Answer:" No. Then it went on searching and asked, "Does the Person1 prototype have a Sayname attribute?" "A:" Yes. So it reads the function that is stored in the prototype object. When we call Person2.sayname (), we will reproduce the same search process and get the same results. This is where multiple object instances share the fundamentals of the properties and methods saved by the prototype.

Looking at the above principle, let's give an example:

functionPerson () {} Person.prototype.name= "Nicholas"; Person.prototype.age= 29; Person.prototype.job= "Software Engineer"; Person.prototype.sayName=function() {alert ( This. Name);        }; varPerson1 =NewPerson (); varPerson2 =NewPerson (); Person1.name= "Greg"; alert (person1.name); //"Greg"-from the examplealert (person2.name);//"Nicholas"-from the prototype

This example shows that when the code reads the object properties, it looks for its own object instance Person1, and when the name is found in the instance, it will not find the corresponding attribute in the object prototype, and if it is not found, continue to search the prototype object ....
In other words, when there are properties in the instance that have the same name as the prototype object, the attributes and property values in the instance are selected first ....
To person1.name display Nicholas here, you need to use Delete.person1.name to delete the same name attribute in the instance ...

The next question is, sometimes we need to detect whether a property is in an instance or in a prototype object.
hasOwnProperty () is inherited from object, and the hasOwnProperty () method can detect whether a property exists in a prototype or an object instance.onlyReturns True when there is an Object object instance (in fact there is a prototype, or false is returned in other non-object instances)
In: Returns True when the specified property is accessible through the object (as long as it can be accessed, whether it exists in an instance or in a prototype)

You can encapsulate a function to determine whether a property exists in an object or in a prototype:
function Hasprototypepropery (obj,name) {
return!obj.hasownproperty (name) && (name in obj);
};
Some people will be puzzled, Hasprototypepropery () method is enough, ah, why also in? I was so confused at first, and I knew it in reverse thinking ...
Suppose now I want to make sure that a property exists in the prototype object, and that Hasprototypepropery () can only be determined to exist in the object instance and not in the object instance, so only when!obj.hasownproperty (name) in the non-instance object and can be accessed through the object to the property, to be sure that it must be in the object prototype,,,, (do not know slowly to think)

We used the prototype approach to solve the shortcomings of the factory and the constructor, but the prototype is a bit more responsible for the code, there are so many duplicate objects. Prototype so we're going to rewrite it.

function Person () {            };        Person.prototype () {            name:' jxj1 ', age            :$,            job:' student ',            showname:  function() {                alert (this. Name);            }        };


This method of writing the prototype object by the object literal is the same as the original one, but there is a change, the previous said that each creation of a function, the function will produce a prototype property, point to the object prototype, and the object prototype
The constructor property points to the created function, and now the constructor property no longer points to person, adapting exponentially to the object constructor
If you need the constructor attribute is important, you can rewrite it:

function Person () {            };        Person.prototype () {            Constructor:person,            name:' jxj1 ', age            : $,            job:' Student ',            showname:function() {                alert (this. Name);            }        } ;

The importance of native mode is only reflected in the types of customizations above, even native reference classes are created in this pattern. Native reference types (Object, Array, String, and so on) all define methods on the prototype of their constructors
For example, the sort () method can be found in array.prototype, and the substring () method can be found in String.prototype, as shown below.
Alert (typeof Array.prototype.sort); "Function"
Alert (typeof String.prototype.substring); "Function"
Similarly, we can also modify the prototype of the native object
The following code gives the basic wrapper type

String adds a method named StartsWith ().
String.prototype.startsWith = function (text) {
return This.indexof (text) = = 0;
};
var msg = "Hello world!";
Alert (Msg.startswith ("Hello")); True

The newly defined StartsWith () method here returns True when the incoming text is at the beginning of a string. Since the method is
is added to String.prototype, all strings in the current environment can be called. Since MSG is a string,
The string basic wrapper function is called in the background to create this, so the StartsWith () method can be called via MSG.

Of course, in non-special cases, it is not recommended to modify the prototype of the native object in the program, and the modified method can produce a naming conflict in other methods.

Disadvantages of the prototype:
Compared to your next prototype and constructor, the prototype pattern omits the initialization parameter, and the result is that all instances share the same attribute value, but we don't see it as a result, which is not the biggest problem.
The biggest problem with native is that it is caused by the nature of sharing that all attributes in the prototype are shared by the instance, and that there is nothing wrong with it, and that the attribute with the same name in the instance has a higher precedence. However, for properties that contain reference type values, the problem is large.
For example:

functionPerson () {} Person.prototype={constructor:person, Name:"Nicholas", Age:29, Job:"Software Engineer", friends: ["Shelby", "Court"], Sayname:function() {alert ( This. Name);        }        }; varPerson1 =NewPerson (); varPerson2 =NewPerson (); Person1.friends.push ("Van"); alert (person1.friends); //"Shelby,court,van"alert (person2.friends);//"Shelby,court,van"Alert (person1.friends = = = Person2.friends);//true



When an instance Person1 object modifies a property that contains a reference type (such as an array), it is reflected in the Person2 object, and since I created two instances, why would I want them to share an array, oh ... On

Now the problem has come again, the prototype also has shortcomings, continue to think about it:
(4) Mixed mode of constructors and prototypes
We need to combine the advantages of both, abandon their shortcomings, analyze it
First, the methods in the constructor will be different each time the instantiation, but the prototype can correct this disadvantage, so the prototype model to define the method
Second, when one of the instances changes the value of the reference type in the prototype, and the corresponding value of the other instance in the prototype changes, the constructor can get rid of the disadvantage, so the constructor pattern defines the property of the reference type value
As a summary, constructors are used to define the properties of an instance, including the base data type and the reference data type, and the prototype pattern is used to define methods and shared properties.
Example: This example is the example we cited earlier

functionPerson (name,age,job) { This. name=name;  This. age=Age ;  This. job=job;  This. friend=[' A1 ', ' A2 '];            }; Person.prototype={Constructor:person, ShowName:function() {alert ( This. Name);            }            }; varp1=NewPerson (' jxj1 ', ' student '); varP2=NewPerson (' jxj2 ', ' student '); P1.friend.push (' A3 '); alert (p1.friend);//' A1,a2,a3 'alert (p2.friend);//' A1,A2 'alert (p1.friend==p2.friend);//falsealert (p1.showname==p2.showname);//true


As can be seen from the example, now the data value of the reference type is not shared, and the function method becomes shared, so there seems to be no problem ....
(5), dynamic prototype mode
Dynamic prototype mode, which encapsulates all information in a constructor, while preserving the advantages of using constructors and prototypes while initializing the prototype in the constructor (only if necessary). In other words, you can
Check whether a method that should exist is valid to determine whether the prototype needs to be initialized. Take a look at an example:

functionPerson (name, age, job) {//Properties             This. Name =name;  This. Age =Age ;  This. Job =job; //Method            if(typeof  This. sayname! = "function") {Person.prototype.sayName=function() {alert ( This. Name);            }; }        }        varFriend =NewPerson ("Nicholas", "Software Engineer"); Friend.sayname ();


This is only added to the prototype if the Sayname () method does not exist. This code will only be executed when the constructor is first called. Since then, the prototype has been initialized and there is no need to make any changes.
Keep in mind, however, that the modifications made to the prototype here can be immediately reflected in all instances. So this approach is really perfect. Where the IF statement can check for any property or method that should exist after initialization--without having to use a lot of
The IF statement examines each property and each method; Just check one of them. For objects created with this pattern, you can also use the instanceof operator to determine its type.
You cannot use object literals to rewrite prototypes when using dynamic prototype mode. If you rewrite the prototype with the instance already created, the connection between the existing instance and the new prototype is severed.

Object-Oriented Programming-fundamentals (factory, constructor, prototype, hybrid, dynamic, etc.)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.