JavaScript Object-oriented (prototype prototype mode)

Source: Internet
Author: User
Tags hasownproperty

First, JavaScript Design Ideas

In 1994, Netscape (Netscape) released the Navigator browser version 0.9. This is the first more mature web browser in history, sensation. However, this version of the browser can only be used to browse, do not have the ability to interact with visitors. For example, if the page has a column "user name" required to fill in, the browser will not be able to determine whether the visitor is actually filled out, only to let the server side judge. If not filled out, the server side will return an error, requiring users to re-fill, which is a waste of time and server resources.

As a result, Netscape is in dire need of a web scripting language that allows browsers to interact with Web pages. Engineer _brendan Eich_ is responsible for developing this new language. He felt that there was no need to design complex, this language as long as the ability to complete some simple operation is enough, such as to determine whether users fill out the form.

1994 was the most prosperous time for object-oriented programming (object-oriented programming), when C + + was the most popular language of the time, and the Java language version 1.0 was about to launch in the second year, and Sun was making a big push.

Brendan Eich is undoubtedly affected by the fact that all data types in JavaScript are objects (object), which is very similar to Java. However, he immediately encountered a problem, in the end should not design "inheritance" mechanism?

If it is really a simple scripting language, there is no need for an "inheritance" mechanism. However, JavaScript is all objects, and there must be a mechanism to link all objects together. As a result, Brendan Eich finally designed the "inheritance".

However, he does not intend to introduce the concept of "class", because once the "class", JavaScript is a complete object-oriented programming language, which seems to be a bit too formal, and increase the beginner's entry difficulty.

He considers that both theC + + and Java languages use the new command to generate an instance.

C + + is written as:     ClassName *object = new ClassName (param); The Java notation is:    foo foo = new Foo ();

  

Therefore, he introduces the new command to JavaScript, which is used to generate an instance object from the prototype object. However, JavaScript does not have a "class", how to represent a prototype object?
At this point, he thought that C + + and Java would invoke the constructor of the class (constructor) when using the new command. He made a simplified design, in the JavaScript language, the new command was followed by a constructor instead of a class.

  Cases:

Now there is a constructor called dog, which represents the prototype of the canine object.

    function DOG (name) {        this.name = name;    }

  

Using new with this constructor will generate an instance of a dog object.

    var DogA = new DOG (' Mao ');    alert (doga.name); Da Mao

  

Note the This keyword in the constructor, which represents the newly created instance object.

  New Disadvantages of Operators

    One disadvantage of generating instance objects with constructors is that you cannot share properties and methods.

Like what:

In the constructor of the dog object, set the common properties of an instance object species

    function DOG (name) {        this.name = name;        this.species = ' Canine branch ';    }

  

Then, build two instance objects:

    var DogA = new DOG (' Mao ');    var dogb = new DOG (' Er Mao ');

The species property of the two objects is independent, modifying one and not affecting the other.

    doga.species = ' Cat Department ';    alert (dogb.species); The pop-up value is "canine", which is unaffected by DogA

  

Each instance object has its own copy of the properties and methods. This not only can not do data sharing, but also a huge waste of resources.

Second, prototype Introduction of Attributes

  Brendan Eich sets a prototype property for the constructor function.

This property contains an object (hereinafter referred to as the "prototype object"), where all instance objects need to share properties and methods that are placed inside the object, and those that do not need to be shared are placed inside the constructor.

Once the instance object is created, the properties and methods of the prototype object are automatically referenced. In other words, the properties and methods of an instance object are divided into two types, one local and the other referenced.

  Cases:

    function DOG (name) {        this.name = name;    }    dog.prototype = {species: ' Canine branch '};        var DogA = new DOG (' Mao ');    var dogb = new DOG (' Er Mao ');        alert (doga.species); Canine    alert (dogb.species);//Canine Department

  

Now, the species attribute is placed in the prototype object, which is shared by two instance objects. As long as the prototype object is modified, it affects two instance objects at the same time.

    DOG.prototype.species = ' Cat Department ';    alert (doga.species); Cat    alert (dogb.species);//Cat Department

  

Three,Prototype prototype Model

  The prototype object is actually an instance object of the constructor, and there is no intrinsic difference from the normal instance object. You can include shared properties or methods for all instances of a specific type. The attribute value of this prototype is an object (a collection of attributes), and the default is only a property called constructor, which points to the function itself.

For example, we simply define a function that supertype a name.

    function supertype () {    }

  There's nothing inside the function that looks like that.

From what we see, there is nothing in the function, but there is a default prototype property, it is an object, it points to its own address, and prototype the object itself has a property constructor, and this property, which points to the function itself

    Alert (supertype.prototype)//object    alert (SuperType.prototype.constructor)//popup function itself functions Supertype () {}

  

  1 , Basic prototypes

    function person () {}      Person.prototype.name = "Nicholas";     Person.prototype.age =;     Person.prototype.job = "Software Engineer";     Person.prototype.sayName = function () {             alert (this.name);     };  

  

This approach is only illustrative of the prototype, which is rarely used to write attributes in the prototype.

  2 , a simpler way

    function person () {}      Person.prototype = {             name: "Nicholas",             age:29,             job: "Software Engineer",             Sayname:function () {                     alert (this.name);             }     

  

This is just a simple way to write all the properties directly through the object literal. The effect is the same as the above, but it is not the same as the wording.

But it's not realistic to write all of the properties and methods directly in the prototype, see the following:

   function person () {}     Person.prototype = {             Constructor:person,             name: "Nicholas",             age:29,             Job: "Software Engineer",             friends: ["Shelby", "Court"],             sayname:function () {                     alert (this.name); 
   
    }     };      var person1 = new Person ();     var person2 = new Person ();      Person1.friends.push ("Van");      alert (person1.friends);    "Shelby,court,van"     alert (person2.friends);    "Shelby,court,van"     alert (person1.friends = = = Person2.friends);  True  
   

  

The above is easy to see, the problem of writing attributes in the prototype, sake friends is the array, the reference data type in Person1 modified friends, after adding a bar of data, You can see that the friends of the Person1 and Person2 objects have changed, which is very well understood, because the prototype object itself is shared, the array is a reference type, changes one, and the rest changes.

So, the more methods used in practice are the way in which constructors are combined with prototypes

  3 , How constructors and prototypes are combined

   function person (name, age, Job) {             this.name = name;             This.age = age;             This.job = job;             This.friends = ["Shelby", "Court"];     }      Person.prototype = {             Constructor:person,   //Remember to write this code to prevent memory leaks            sayname:function () {                     alert ( this.name);             }     }     var person1 = new Person ("Nicholas", "Software Engineer");     var person2 = new Person ("Greg", "Doctor");      Person1.friends.push ("Van");     alert (person1.friends);    "Shelby,count,van"     alert (person2.friends);    "Shelby,count"     alert (person1.friends = = = Person2.friends);    False     alert (person1.sayname = = = Person2.sayname);    True   

  

As you can see here, friends's properties change one of the two objects without affecting the other. This constructor-plus-prototype compositing pattern is the way of a custom type that currently uses the highest rate of recognition, so, in general, we define custom types by default using this pattern

  4 , Dynamic prototyping mode

This pattern is just the variant of the above pattern, for some accustomed to writing object-oriented language programmer, a class to separate two parts to write, is very unaccustomed to, so, there is a dynamic prototype mode, in fact, the two parts of the previous part of the content, all mentioned function, plus judgment on the line

    function person (name, age, Job) {          //attribute          this.name = name;             This.age = age;             This.job = job;         Method          if (typeof this.sayname! = "function") {                          Person.prototype.sayName = function () {                             alert (this.name);                     };                      }     }      var friend = new Person ("Nicholas", "Software Engineer");     Friend.sayname ();  

  

Note The above judgment, this way only if the Sayname function does not exist, it will be added to the prototype, if the Sayname function already exists, then this code will not run again, and even if there are many methods, if the statement does not have to judge all, just need to judge one on the line.

This way of writing, for Java or C # programmers is relatively more receptive to the senses, and there is no flaw in the wording. However, one thing is not a flaw, JavaScript is a dynamic language, that is, properties and methods can be added at any time, if all written in the constructor, but it does not seem so flexible. So, in general, the blending mode of using constructors and prototypes

Four, Prototype validation methods for schemas

  To match the prototype attribute, JavaScript defines some helper methods

  1, isprototypeof (): This method is used to determine the relationship between a Proptotype object and an instance.

function Cat (name,color) {        this.name = name;        This.color = color;    }    Cat.prototype.type = "Feline animal";    Cat.prototype.eat = function () {alert ("Eat Mouse")};      var cat1 = new Cat ("Da Mao", "Yellow");    var cat2 = new Cat ("Er Mao", "Black"); Alert (Cat.prototype.isPrototypeOf (CAT1));  True to    determine if the CAT1 object is a prototype prototype  alert (Cat.prototype.isPrototypeOf (CAT2));//true    Determines if Cat2 object is prototype Prototype

  2 . hasOwnProperty (): Used to determine whether a property is a local property or a property inherited from a prototype object.

    function Cat (name,color) {        this.name = name;        This.color = color;    }    Cat.prototype.type = "Feline animal"; Alert (Cat1.hasownproperty ("name")); True the    Name property is a local property     of alert (Cat1.hasownproperty ("type"));//False The   Type property is a property of the inherited prototype object

  

  3 , inch operator

The in operator can be used to determine whether an instance contains a property, whether it is a local property or not.

    Alert ("name" in CAT1); True    alert ("type" in CAT1);//True  

  The in operator can also be used to traverse all properties of an object.  

    For (Var prop in cat1) {         alert ("cat1[" +prop+ "]=" +cat1[prop]);     }

  V. description and Description of the prototype in the Advanced JavaScript programming book

    The function person () {}  //creates the person constructor    Person.prototype.name = "Nicholas";  Create a shared property name     Person.prototype.age =;  Create a shared property age     Person.prototype.job = "Software Engineer";   Create a shared property job     Person.prototype.sayName = function () {     //create shared function Sayname       alert (this.name); }        //Created Person1 and Person2, each with sayname function, and the value of the popup is the same as    var person1 = new Person ();     Person1.sayname ();   "Nicholas"      var person2 = new Person ();    Person2.sayname ();   "Nicholas"      alert (person1.sayname = = person2.sayname);  True   

  

From the diagram above, you can see that Person1 and Person2 have a pointer to person.prototype inside them, which can be tested by the Isprototype method of the prototype.

    Alert (Person.prototype.isPrototypeOf (Person1));  True    alert (Person.prototype.isPrototypeOf (Person2));  True    function User () {};    var person3 = new User ();    Alert (Person.prototype.isPrototypeOf (Person3));  False  is not a prototype prototype object    alert (User.prototype.isPrototypeOf (Person3));  True     is a prototype prototype object

  

Many methods of array manipulation (such as concat, join, push) should also be defined in the prototype property.
In fact, all of JavaScript's intrinsic data types have a read-only prototype property (which is understandable: because if these types of prototype properties are modified, the predefined methods disappear), but we can add our own extension methods to them.

   Extend a method that gets the minimum value to the JavaScript intrinsic type Array        Array.prototype.min = function () {            var min = this[0];            for (var i = 1; i < this.length; i++) {                if (This[i] < min) {                    min = this[i];                }            }            return min;        };                The Min method is called on an instance of any array        console.log ([1, +, 12].min ());  

  

Note: Here is a trap that, when you add an extension method to the array's prototype, the extension method is also recycled when using the For-in loop array.

The following code illustrates this (assuming that the Min method has been extended to the array's prototype):

    var arr = [1, +/--+];        var total = 0;        for (var i in arr.) {Total            + = parseint (Arr[i]);        }        Console.log (total);   NaN  

  

The workaround is also simple:

    var arr = [1, +/--+];        var total = 0;        for (var i in arr) {            if (Arr.hasownproperty (i)) {total                + = parseint (Arr[i], ten);}        }        Console.log (total);   103

  

Six, Constructor

  Constructor always points to the constructor that creates the current object.

Cases: 

Equivalent to var foo = new Array (1, +, +);        var arr = [1, +/--+];        Console.log (Arr.constructor = = = Array); True        //equivalent to var foo = new Function ();        var Foo = function () {};        Console.log (Foo.constructor = = = Function); True        //instantiated by the constructor of an obj object        var obj = new Foo ();        Console.log (Obj.constructor = = = Foo); True        //Put the above two pieces of code together and get the following conclusion        

  

When constructor encounters prototype, each function has a default property prototype, and this prototype constructor by default points to this function.

Cases:

   function person (name) {            this.name = name;        };        Person.prototype.getName = function () {            return this.name;        };        var p = new Person ("every day");                Console.log (P.constructor = = = person);  True        console.log (Person.prototype.constructor = = person);//True        //combine the last two lines of code to get the following results        Console.log ( P.constructor.prototype.constructor = = = person); True

  

When we re-define the function's prototype (note: the difference between the above example, here is not a modification but overwrite ), constructor's behavior is a bit strange,

Cases:

    function person (name) {            this.name = name;        };        Person.prototype = {            getname:function () {                return this.name;            }        };        var p = new Person ("Zhangsan");        Console.log (P.constructor = = = person);  False        console.log (Person.prototype.constructor = = = person);//False        Console.log ( P.constructor.prototype.constructor = = = person); False  

  

The reason for the result of the above code is that when overwriting person.prototype, it is equivalent to doing the following code:

    Person.prototype = new Object ({            getname:function () {                return this.name;            }        

  

and constructor always points to the constructor that created itself, so at this point Person.prototype.constructor = = = Object, which is:

    function person (name) {            this.name = name;        };        Person.prototype = {            getname:function () {                return this.name;            }        };        var p = new Person ("every day");        Console.log (P.constructor = = = Object);  True        console.log (Person.prototype.constructor = = = Object);//True        Console.log ( P.constructor.prototype.constructor = = = Object); True

  

Here's how to modify the problem, which is simply to re-overwrite the Person.prototype.constructor:

   function person (name) {            this.name = name;        };        Person.prototype = new Object ({            getname:function () {                return this.name;            }        });        Person.prototype.constructor = person;  Let it re-point at its own constructor        var p = new Person ("Zhangsan");        Console.log (P.constructor = = = person);  True        console.log (Person.prototype.constructor = = = person);//True        Console.log ( P.constructor.prototype.constructor = = = person); True

  

Vii. __proto__ implicit prototypes of objects

Above we created two objects, Person1 and Person2, both of which point to the prototype of the person constructor, because each object has a hidden property "__proto__" that references the prototype of the function that created the object. That is: person1.__proto__ = = = Person.prototype
This __proto__ is a hidden property, JavaScript does not want developers to use this property value, and some low-version browsers do not even support this property value.

Use its code as follows:

    Console.log (object.prototype);    var obj = new Object ();    Console.log (obj.__proto__);

You will find that the same content was printed :

obj is essentially created by the object function, so obj.__proto__=== object.prototype. Can be represented by a graph.

JavaScript Object-oriented (prototype prototype mode)

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.