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)