Home > Article > Web Front-end > Understanding JavaScript
Introduction
There are only two basic elements in the programming world, one is data and the other is code. The world of programming shows infinite vitality and vitality in the inextricable entanglement of data and code.
Data is inherently quiet and always wants to maintain its inherent nature; while code is inherently lively and always wants to change the world.
You see, the relationship between data codes is surprisingly similar to the relationship between matter and energy. Data also has inertia. If there is no code to exert external force, it will always maintain its original state. Code is like energy. The only purpose of its existence is to work hard to change the original state of the data. When the code changes the data, it will also in turn affect or change the original trend of the code due to the resistance of the data. Even in some cases, data can be converted into code, and code may be converted into data. There may be a digital conversion equation similar to E=MC2. However, it is in this contradictory yet unified operation between data and code that the laws of the computer world can always be reflected. These laws are exactly the program logic we write.
However, because different programmers have different worldviews, these data and codes look different. As a result, programmers with different worldviews use their own methodologies to promote the evolution and development of the programming world.
As we all know, the most popular programming idea today is the idea of object-oriented programming. Why can object-oriented ideas quickly become popular in the programming world? Because object-oriented thinking combines data and code into a unity for the first time and presents it to programmers with a simple object concept. This suddenly divides the original messy algorithms and subroutines, as well as the entangled complex data structures, into clear and orderly object structures, thus clarifying the messy knot of data and code in our hearts. We can have a clearer mind and explore the vaster programming world from another level of thinking.
One day after the Fifth Patriarch Hongren finished teaching the "Object True Sutra", he said to all his disciples: "I have finished teaching. I think you should have some insights. Please each write a verse to read." The eldest disciple, Shenxiu, is recognized as the senior brother with the highest understanding. His verse reads: "The body is like an object tree, and the mind is as bright as its kind. Wipe it diligently and don't let it get dusty!". As soon as this verse came out, it immediately caused a sensation among the brothers. Everyone said it was so well written. Only the fire-headed monk Huineng sighed softly after looking at it, and wrote on the wall: "The object has no roots, and the type is invisible. There is nothing in the first place, so where can it cause dust?" Then he shook his head and walked away. Everyone who read Hui Neng's gatha said, "It's written in such a mess that I can't understand it." Master Hongren read Shenxiu's verse and nodded in praise, and then looked at Huineng's verse and shook his head silently. That night, Hongren quietly called Huineng to his meditation room, taught him the software scriptures that he had treasured for many years, and then asked him to escape overnight under the moonlight...
Later, Huineng really lived up to his master's high expectations. Created another vast sky for Zen Buddhism in the south. One of the software scriptures that Huineng took away was the "JavaScript Scripture"!
Back to simplicity
To understand JavaScript, you must first let go of the concepts of objects and classes and return to the origins of data and code. As mentioned before, the programming world has only two basic elements: data and code, and these two elements are intertwined. JavaScript simplifies data and code to the most primitive level.
Data in JavaScript is very concise. There are only five types of simple data: undefined, null, boolean, number and string, while there is only one type of complex data, namely object. This is like classical Chinese simple materialism, which classifies the most basic elements of the world as metal, wood, water, fire, and earth, and other complex substances are composed of these five basic elements.
Code in JavaScript is only reflected in one form, which is function.
Note: The above words are all lowercase, do not confuse them with JavaScript built-in functions such as Number, String, Object, Function, etc. You know, the JavaScript language is case-sensitive!
Any JavaScript identifier, constant, variable and parameter is just one of unfined, null, bool, number, string, object and function types, which is what typeof returns The type indicated by the value. There is no other type besides this.
Let’s talk about simple data types first.
undefined: Represents all unknown things, nothing, unimaginable, and the code cannot handle it.
petrelrelure, blown, tears, tears, she Shen- she Shen Shen Shen Shen Shen everywhere she she hopes she she races she her All she she she she she she needs she with E It can assign Undefined to any variable or attribute, but it does not mean that the variable is cleared, but it will have an additional attribute.
boolean: Yes is, no is no, there is no doubt. Right is right, wrong is wrong, absolutely clear. It can be processed by the code and can also control the flow of the code.
Number: Linear things, clear in size and order, numerous but not chaotic. It facilitates batch processing of code, and also controls the iteration and looping of code.
spotsurustenururelrel - blown,ururel, she Shen Shen Shen Shen Shen Shen Shen Shen Shen Shen Shen Shen Shen her, her ordns to do herself to do her for. The structure NaN participates in any numerical calculation is NaN, and NaN != NaN.
String: Rational things for humans, not machine signals. Human-computer information communication, code understanding of human intentions, etc. all rely on it.
Simple types are not objects, and JavaScript does not give these simple types the ability to objectify. Identifiers, variables, and parameters that are directly assigned constant values of simple types are not objects.
The so-called “objectification” is the ability to organize data and code into complex structures. In JavaScript, only the object type and function type provide objectification capabilities.
There is no class
Object is the type of object. In JavaScript, no matter how complex the data and code are, they can be organized into objects in the form of objects.
But JavaScript does not have the concept of "class"!
For many object-oriented programmers, this is probably the most difficult thing to understand in JavaScript. Yes, in almost any object-oriented book, the first thing to talk about is the concept of "class", which is the pillar of object-oriented. Suddenly there is no "category", and we feel like we have lost our spiritual support and feel that we have no master. It seems that it is not easy to let go of objects and classes and reach the state where "objects have no roots and types are invisible".
So, let’s look at a JavaScript program first:
var life = {};
for(life.age = 1; life.age <= 3; life.age++)
{
switch(life.age)
{
case 1: life.body ";
life .gill = "gill";
life.body = "tadpole";
life.say = function(){alert(this.age+this.body+"-"+this.tail+","+this.gill)} ;
break; life.lung = "Lung"; say = function(){alert(this.age+this.body+"-"+this.legs+","+this.lung)};
break; This JavaScript program initially generated a life object, life. When life was born, it was just a bare object without any properties or methods. In the first life process, it has a body attribute and a say method, which looks like an "egg cell". During its second life, it grew a "tail" and "gills". With the tail and gill attributes, it was obviously a "tadpole". During its third life, its tail and gill attributes disappeared, but it grew "four legs" and "lungs", acquired the legs and lung attributes, and finally became a "frog". If you have a rich imagination, you may be able to turn it into a handsome "prince" and marry a beautiful "princess" or something. However, after reading this program, please think about a question:
Do we definitely need classes?
Do you still remember the fairy tale of "little tadpole looking for its mother" when you were a child? Maybe just last night, your child happened to fall asleep in this beautiful fairy tale. The cute little tadpole gradually became the same "kind" as its mother during the continuous evolution of its own type, and thus found its mother. The programming philosophy contained in this fairy tale is: the "class" of an object comes from scratch, continues to evolve, and eventually disappears...
"Class" can indeed help us understand complex reality The world, this chaotic real world does need to be classified. But if our thoughts are bound by "category", "category" will become "tired". Imagine, if a living object is assigned a fixed "class" from the beginning, can it still evolve? Can a tadpole turn into a frog? Can you also tell the children the story of a tadpole looking for its mother?
Therefore, there is no "class" in JavaScript. Classes have become invisible and integrated with objects. It is precisely because of letting go of the concept of "class" that JavaScript objects have vitality that other programming languages do not have.
If, at this time, you begin to feel something deep in your heart, then you have gradually begun to understand the Zen of JavaScript.
The magic of functions
Next, let’s discuss the magic of JavaScript functions.
JavaScript code has only one form of function, and function is the type of function. Maybe other programming languages have code concepts such as procedure or method, but in JavaScript there is only one form of function. When we write a function, we just create an entity of type function. Please look at the following program:
function myfunc()
{
alert("hello");
};
alert(typeof(myfunc));
After running this code, you can see that typeof(myfunc) returns function. We call the above function writing method "definition formula". If we rewrite it into the following "variable formula", it will be easier to understand:
var myfunc = function ()
;
alert(typeof(myfunc)); Therefore, typeof(myfunc) also returns function. In fact, the writing methods of these two functions are equivalent, and except for a few minor differences, their internal implementation is exactly the same. In other words, the JavaScript functions we write are just named variables. The variable type is function, and the value of the variable is the function code body we wrote.
You may be smart and ask further questions immediately: Since functions are just variables, variables can be assigned values arbitrarily and used anywhere???/p>
var myfunc = function ( )
. "yeah");};
myfunc(); //The second call to myfunc will output yeah
The result of running this program tells us: the answer is yes! After the function is called for the first time, the function variable is assigned a new function code body, so that when the function is called for the second time, different output appears.
Okay, let’s change the above code into the first defined function form:
function myfunc ()
{
alert("hello");
};
myfunc(); //Call here myfunc, output yeah instead of hello
function myfunc ()
{
};
myfunc(); //myfunc is called here, of course it outputs yeah
Logically speaking, the two signatures are exactly the same functions that should be illegal in other programming languages. But in JavaScript, this is true. However, after the program was run, a strange phenomenon was discovered: the two calls were only the values output by the last function! Obviously the first function doesn't do anything. This is why?
It turns out that the JavaScript execution engine does not analyze and execute the program line by line, but analyzes and executes it piece by piece. Moreover, during the analysis and execution of the same program, the defining function statements will be extracted and executed first. After the function definition is executed, other statement codes will be executed in sequence. That is to say, before myfunc is called for the first time, the code logic defined by the first function statement has been overwritten by the second function definition statement. Therefore, both calls execute the last function logic.
If you divide this JavaScript code into two pieces, for example, write them in an html, and use the tag to divide it into two pieces like this:
<script><br> function myfunc ()<br> {<br> alert ("hello");<br> };<br> myfunc(); //Call myfunc here and output hello</p></script>
At this time, the output comes in order, which also proves that JavaScript is indeed executed piece by piece.
Defined function statements in a piece of code will be executed first, which seems a bit like the compilation concept of static languages. Therefore, this feature is also called by some people: JavaScript "pre-compilation".
In most cases, we don’t need to get entangled in these details. As long as you remember one thing: the code in JavaScript is also a kind of data, which can also be assigned and modified arbitrarily, and its value is the logic of the code. However, unlike general data, functions can be called and executed.
However, if JavaScript functions are only good at this, how strange is this compared with C++’s function pointer, DELPHI’s method pointer, and C#’s delegate! However, the magic of JavaScript functions is also reflected in two other aspects: one is that the function type itself also has the ability to be objectified, and the other is the transcendent ability to combine functions with objects.
Wonderful Objects
Let’s first talk about the objectification ability of functions.
Any function can dynamically add or remove attributes for it. These attributes can be simple types, objects, or other functions. In other words, functions have all the characteristics of objects, and you can use functions as objects. In fact, a function is an object, but it has one more bracket "()" operator than a normal object. This operator is used to execute the logic of the function. That is, the function itself can still be called, but the general object cannot be called, except that it is exactly the same. Please look at the code below:
function Sing()
{
with(arguments.callee)
alert(author + ":" + poem);
};
Sing.author = "李白";
Sing.poem = " The moon in the Qin Dynasty of the Han Dynasty illuminates the concubine as soon as she reaches the end of the world. The moon sets in front of the Yin Mountain. My daughter's pipa has been singing for three thousand years.";
Sing();
In this code, after the Sing function is defined, the author and poem attributes are dynamically added to the Sing function. Setting the author and poem attributes to different authors and poems will display different results when calling Sing(). This example uses a poetic way to let us understand that JavaScript functions are the essence of objects, and also feel the beauty of JavaScript language.
var anObject = {}; //An object
anObject.aProperty = "Property of object"; //A property of the object anObject.aMethod = function(){ alert("Method of object")}; //A method of an object
//Mainly look at the following:
alert(anObject["aProperty"]); //You can use the object as an array and use the property name as a subscript to access properties
anObject["aMethod"](); //You can use the object as an array and use the method name as a subscript to call the method
for( var s in anObject) //Traverse all properties and methods of the object for iterative processing
alert( s + " is a " + typeof(anObject[s]));
The same is true for objects of function type:
var aFunction = function() {}; //A function
aFunction.aMethod = function(){alert("Method of function")}; //A method of the function
//Mainly look at the following:
alert(aFunction["aProperty"]) ; //You can use the function as an array and use the attribute name as a subscript to access properties
aFunction["aMethod"](); ) // All the attributes and methods of traversing the function are iterated
Alert (S + "is a" + Typeof (AFUNCTION [s]);
Yes, objects and functions can be accessed and processed like arrays, using property names or method names as subscripts. So, should it be considered an array or an object?
We know that arrays should be regarded as linear data structures. Linear data structures generally have certain rules and are suitable for unified batch iteration operations. They are a bit like waves. Objects are discrete data structures, suitable for describing dispersed and personalized things, a bit like particles. Therefore, we can also ask: Are objects in JavaScript waves or particles?
If there is object quantum theory, then the answer must be: wave-particle duality!
Therefore, functions and objects in JavaScript have the characteristics of both objects and arrays. The array here is called a "dictionary", a collection of name-value pairs that can be arbitrarily expanded. In fact, the internal implementation of object and function is a dictionary structure, but this dictionary structure shows a rich appearance through rigorous and exquisite syntax. Just as quantum mechanics uses particles to explain and deal with problems in some places, and waves in other places. You can also freely choose to use objects or arrays to explain and handle problems when needed. As long as you are good at grasping these wonderful features of JavaScript, you can write a lot of concise and powerful code.
Put down the object
Let’s take a look at the transcendent combination of function and object.
In the world of object-oriented programming, the organic combination of data and code constitutes the concept of objects. Since the creation of objects, the programming world has been divided into two parts, one is the world within the object, and the other is the world outside the object. Objects are inherently selfish, and the outside world cannot access the inside of the object without permission. Objects also have a generous side. They provide properties and methods to the outside world and serve others. However, here we have to talk about an interesting issue, which is "self-awareness of the object".
What? Did you hear that right? Is the subject self-aware?
Maybe for many programmers, this is indeed the first time they have heard of it. However, please take a look at this in C++, C# and Java, self in DELPHI, and me in VB, maybe you will suddenly realize it! Of course, it is possible to just say "nothing more than that".
However, when the object divides the world into internal and external parts, the object's "self" also emerges. "Self-awareness" is the most basic feature of life! It is precisely because of the powerful vitality of objects that the programming world is full of infinite vitality and vitality.
But the object’s “self-awareness” brings us happiness but also pain and troubles. We attach too many desires to objects, always hoping they can do more. However, the selfishness of objects makes them compete with each other for system resources, the egotism of objects makes objects complex and bloated, and the self-deception of objects often brings lingering errors and exceptions. Why do we have so much pain and trouble?
To this end, there was a person who thought for ninety-nine and eighty-one days under the object tree, and finally realized that the pain of life comes from desire, but the root of desire comes from self-awareness. So he put down his "self" and became a Buddha under the object tree. From then on, he began to save all sentient beings and spread the true scriptures. His name is Sakyamuni, and the "JavaScript Sutra" is one of the scriptures he preached.
There is also this in JavaScript, but this this is different from this in languages such as C++, C# or Java. In general programming languages, this is the object itself, but in JavaScript this is not necessarily the case! This may be me, it may be you, it may be him. Anyway, you are in me, and I am in you. Therefore, you cannot use the original "self" to understand the meaning of this in JavaScript. To do this, we must first let go of the "self" of the original object.
Let’s look at the following code:
function WhoAmI() //Define a function WhoAmI
{
alert("I'm " + this.name + " of " + typeof(this));
};
WhoAmI(); //This is the global object of this current code. In the browser, it is the window object, and its name attribute is an empty string. Output: I'm of object
var BillGates = {name: "Bill Gates"};
BillGates.WhoAmI = WhoAmI; //Use function WhoAmI as a method of BillGates.
BillGates.WhoAmI(); //This is BillGates at this time. Output: I'm Bill Gates of object
var SteveJobs = {name: "Steve Jobs"};
SteveJobs.WhoAmI = WhoAmI; // Use function WhoAmI as a method of SteveJobs.
SteveJobs.WhoAmI(); //This is SteveJobs at this time. Output: I'm Steve Jobs of object
WhoAmI.call(BillGates); // Directly use BillGates as this and call WhoAmI. Output: I'm Bill Gates of object
WhoAmI.call(SteveJobs); // Directly use SteveJobs as this and call WhoAmI. Output: I'm Steve Jobs of object
BillGates.WhoAmI.call(SteveJobs); // Use SteveJobs as this, but call BillGates's WhoAmI method. Output: I'm Steve Jobs of object
SteveJobs.WhoAmI.call(BillGates); //Use BillGates as this, but call SteveJobs's WhoAmI method. Output: I'm Bill Gates of object
WhoAmI.WhoAmI = WhoAmI; //Set the WhoAmI function as its own method.
WhoAmI.name = "WhoAmI";
WhoAmI.WhoAmI(); //This at this time is the WhoAmI function itself. Output: I'm WhoAmI of function
({name: "nobody", WhoAmI: WhoAmI}).WhoAmI(); Output: I'm nobody of object
Create an object without any properties:
var o = {};
var person = {name: "Angel", age: 18, married: false};
var speaker = {text: "Hello World", say: function(){alert(this.text)}};
var company =
{
name: "Microsoft",
product: "softwares",
chairman: {name: "Bill Gates", age: 53, Married: true},
employees: [ {name: "Angel", age: 26, Married: false}, {name: "Hanson", age: 32, Marred: true}],
readme: function() {document.write(this.name + " product " + this.product);}
};
The form of JSON is a list of items enclosed in braces "{}", each item is separated by a comma ",", and the item is an attribute name and attribute value separated by a colon ":". This is a typical dictionary representation, and it once again shows that objects in JavaScript are dictionary structures. No matter how complex the object is, it can be created and assigned with a JSON code.
In fact, JSON is the best serialization form of JavaScript objects. It is more concise and space-saving than XML. The object can be used as a string in the form of JSON to freely transmit and exchange information between networks. When you need to turn this JSON string into a JavaScript object, you only need to use the eval function, a powerful digital conversion engine, to get a JavaScript memory object immediately. It is precisely because of the simple and simple natural beauty of JSON that she becomes a dazzling star on the AJAX stage.
JavaScript is like this, expressing seemingly complex object-oriented things in an extremely concise form. Take off your partner’s flashy and heavy makeup, and give your partner a clear-eyed look!
Constructing Objects
Okay, let’s discuss another method of creating objects.
In addition to JSON, in JavaScript we can use the new operator combined with a function to create objects. For example:
function MyFunc() {}; //Define an empty function
var anObj = new MyFunc(); //Use the new operator and use the MyFun function to create an object
This way of creating objects in JavaScript The method is really interesting. How to understand this way of writing?
In fact, the above code can be rewritten into this equivalent form:
function MyFunc(){};
var anObj = {}; //Create an object
MyFunc.call(anObj); //Create anObj object Calling the MyFunc function as this pointer
We can understand it this way. JavaScript first uses the new operator to create an object, and then uses this object as the this parameter to call the following function. In fact, this is what JavaScript does internally, and any function can be called like this! But from the form of "anObj = new MyFunc()", we see a familiar figure again. Isn't this how C++ and C# create objects? It turns out that all roads lead to Lingshan, and they lead to the same destination!
You may be thinking when you see this, why can't we use this MyFunc as a constructor? Congratulations, you got it! JavaScript thinks so too! Please look at the code below:
1 function Person(name) // Constructor with parameters
2 {
3 this.name = name; // Assign parameter values to the properties of this object
4 this.SayHello = function () {alert("Hello, I'm " + this.name);}; //Define a SayHello method for this object.
5 };
6
7 function Employee(name, salary) //Sub constructor
8 {
9 Person.call(this, name); // Pass this to the parent constructor
10 this.salary = salary ; ;
12 };
13
14 var BillGates = new Person("Bill Gates"); //Use the Person constructor to create a BillGates object
15 var SteveJobs = new Employee("Steve Jobs", 1234); //Use the Empolyee constructor The function creates the SteveJobs object
16
17 BillGates.SayHello(); //Show: I'm Bill Gates
18 SteveJobs.SayHello(); //Show: I'm Steve Jobs
19 SteveJobs.ShowMeTheMoney(); // Display: Steve Jobs $1234
20
21 alert(BillGates.constructor == Person); //Display: true
22 alert(SteveJobs.constructor == Employee); //Display: true
23
24 alert(BillGates.SayHello == SteveJobs.SayHello); //Display: false
This code shows that functions can not only be used as constructors, but can also take parameters, and can also add members and methods to objects. In line 9, the Employee constructor calls the Person constructor using the this it receives as a parameter, which is equivalent to calling the base class constructor. Lines 21 and 22 also indicate the following: BillGates is constructed from Person, and SteveJobs is constructed from Employee. The built-in constructor property of the object also specifies the specific function used to construct the object!
In fact, if you are willing to think of a function as a "class", it is a "class" because it already has the characteristics of a "class". Is not it? The sons she gave birth to all have the same characteristics, and the constructor also has the same name as the class!
But it should be noted that each object created by using the constructor to operate this object not only has its own member data, but also has its own method data. In other words, the code body of the method (the data that embodies the function logic) has a copy in each object. Although the logic of each code copy is the same, the objects do each save a copy of the code body. The last sentence in the above example illustrates this fact, which also explains the concept of functions in JavaScript as objects.
It is obviously a waste for objects of the same class to each have a method code. In traditional object languages, method functions are not an object concept like JavaScript. Even though there are variations like function pointers, method pointers or delegates, they are essentially references to the same code. It is difficult for general object languages to encounter this situation.
However, the JavaScript language has great flexibility. We can first define a unique method function body, and use this unique function object as its method when constructing this object, so that the method logic can be shared. For example:
function SayHello() // Define a SayHello function code first
{
alert("Hello, I'm " + this.name);
};
function Person(name) //Construction with parameters Function {{i this.name = name; // assign the parameter value to the attribute of the this object www.2cto.com
this.sayhello = sayhello; // The value of the Sayhello method to the this object is the previous Sayhello code.
};
var BillGates = new Person("Bill Gates"); //Create BillGates object
alert(BillGates.SayHello == SteveJobs .SayHello); //Display: true
Among them, the output result of the last line shows that the two objects do share a function object. Although this program achieves the purpose of sharing a method code, it is not very elegant. Because the definition of the SayHello method does not reflect its relationship with the Person class. The word "elegant" is used to describe code, and I don't know who first proposed it. However, this word reflects that programmers have developed from pursuing the correctness, efficiency, reliability and readability of the code to pursuing the aesthetic feeling and artistic realm of the code. Programming life has become more romantic.
Obviously, JavaScript has already thought of this problem, and its designers have provided an interesting prototype concept for this.
First Look at the Prototype
Prototype comes from French. The standard translation in the software industry is "prototype", which represents the initial form of things and also contains the meaning of models and templates. The concept of prototype in JavaScript appropriately reflects the connotation of this word. We cannot understand it as a pre-declared concept like prototype in C++.
All function type objects in JavaScript have a prototype attribute. The prototype attribute itself is an object of type object, so we can also add arbitrary properties and methods to this prototype object. Since prototype is the "prototype" of an object, the objects constructed by this function should have this "prototype" characteristic. In fact, all properties and methods defined on the prototype of the constructor can be directly accessed and called through the object it constructs. It can also be said that prototype provides a mechanism for a group of similar objects to share properties and methods.
Let’s take a look at the following code first:
function Person(name)
{
this.name = name; //Set object attributes, each object has its own attribute data
};
Person.prototype.SayHello = function() //Add the SayHello method to the prototype of the Person function. Er {
Alert ("Hello, I'm" + this.Name);
}
Var Stevejobs = New Person ("Steve Jobs" "" ; = SteveJobs.SayHello); //Because the two objects are SayHello that share the prototype, it is displayed: true
So, what about constructors of multi-level types?
Let’s look at the following code again:
1 function Person(name) //Base class constructor2 {
3 this.name = name;4 };
5 6 Person.prototype.SayHello = function() // Add method to proprope to the base construct function
7 {
8 Alert ("Hello, I'm" + This.name);
9}; Constructor
12 Person.call(this, name); // Call the base class constructor
14 this.salary = salary; Build a base class object as the prototype of the subclass prototype. This is very interesting. Employee.prototype.ShowMeTheMoney = function() //Add a method to the prototype of the subclass constructor.
20 {
21 alert(this. name + " $" + this.salary);
22 };
23
24 var BillGates = new Person("Bill Gates"); //Create a BillGates object of the base class Person
25 var SteveJobs = new Employee("Steve Jobs", 1234); // Create a SteveJobs object of the subclass Employee
26
27 BillGates.SayHello(); // Call the prototype method directly through the object
28 SteveJobs.SayHello(); // Directly through the subclass object Call the method of the base class prototype, pay attention!
29 SteveJobs.ShowMeTheMoney(); //Directly call the method of the subclass prototype through the subclass object
30
31 alert(BillGates.SayHello == SteveJobs.SayHello); //Display: true, indicating that the prototype method is shared
In line 17 of this code, a base class object is constructed and set as the prototype of the subclass constructor. This is very interesting. The purpose of this is for line 28. The method of the base class prototype can also be directly called through the subclass object. Why is this possible?
It turns out that in JavaScript, prototypes not only allow objects to share their wealth, but prototypes also have the nature of tracing their roots and ancestors, so that the legacy of our ancestors can be passed down from generation to generation. When reading attributes or calling methods from an object, if the object itself does not have such attributes or methods, it will go to the prototype object associated with itself to find it; if the prototype does not have it, it will go to the predecessor prototype associated with the prototype itself. Search until found or until the tracing process is completed.
Within JavaScript, the object’s attribute and method tracing mechanism is implemented through the so-called prototype chain. When an object is constructed using the new operator, the prototype object of the constructor is also assigned to the newly created object and becomes the built-in prototype object of the object. The built-in prototype object of an object should be invisible to the outside world. Although some browsers (such as Firefox) can allow us to access this built-in prototype object, this is not recommended. The built-in prototype object itself is also an object and has its own associated prototype object, thus forming a so-called prototype chain.
At the end of the prototype chain, it is the prototype object pointed to by the prototype attribute of the Object constructor. This prototype object is the oldest ancestor of all objects. This ancestor implements methods such as toString that all objects should inherently have. The prototypes of other built-in constructors, such as Function, Boolean, String, Date and RegExp, are all inherited from this ancestor, but they each define their own properties and methods, so that their descendants show the characteristics of their respective clans. Those characteristics.
Isn’t this “inheritance”? Yes, this is "inheritance", a "prototypal inheritance" unique to JavaScript.
“Prototypal inheritance” is kind and strict. The prototype object selflessly contributes its properties and methods to the children, and does not force the children to comply, allowing some naughty children to act independently according to their own interests and hobbies. In this regard, the archetypal subject is a loving mother. However, although any child can go his own way, he cannot touch the existing property of the prototype object, because that may affect the interests of other children. From this point of view, the prototype object is like a strict father. Let’s take a look at the following code to understand this:
function Person(name)
{
this.name = name;
};
Person.prototype.company = "Microsoft"; //Prototype properties
Person.prototype.SayHello = function() //Prototype method
{
alert("Hello, I'm " + this.name + " of " + this.company);
};
var BillGates = new Person("Bill Gates");
BillGates.SayHello(); //Due to inheriting the prototype, the output is regular: Hello, I'm Bill Gates
var SteveJobs = new Person("Steve Jobs");
SteveJobs.company = "Apple"; //Set your own company property, masking the prototype's company property
SteveJobs.SayHello = function() //Implement your own SayHello method, masking the prototype's SayHello method
{
alert ("Hi, " + this.name + " like " + this.company + ", ha ha ha ");
};
SteveJobs.SayHello(); // They are all properties and methods covered by themselves, output: Hi, Steve Jobs like Apple, ha ha ha
BillGates.SayHello(); // SteveJobs’ override does not affect the prototype object, BillGates still outputs the same as before
Objects can mask those properties and methods of the prototype object, a constructor The prototype object can also mask the existing properties and methods of the upper-level constructor prototype object. This masking actually just creates new properties and methods on the object itself, but these properties and methods have the same names as those of the prototype object. JavaScript uses this simple masking mechanism to achieve the "polymorphism" of objects, which coincides with the concepts of virtual functions and override in static object languages.
However, what is even more amazing than static object language is that we can dynamically add new properties and methods to the prototype object at any time, thus dynamically extending the functional features of the base class. This is difficult to imagine in a static object language. Let’s look at the following code:
function Person(name)
{
this.name = name;
};
Person.prototype.SayHello = function() //Method defined before creating the object
{
alert(" Hello, I'm " + this.name);
};
var BillGates = new Person("Bill Gates"); //Create an object
BillGates.SayHello();
Person.prototype.Retire = function () //Method to dynamically extend the prototype after creating an object
{
alert("Poor " + this.name + ", bye bye!");
};
BillGates.Retire(); //Dynamic expansion The method can be called immediately by the previously created object
Amitābha, prototype inheritance can actually play such a magic!
Prototype Extension
You must have a very high level of understanding. You may think this way: If you add some new methods and properties to the prototype of JavaScript’s built-in functions such as Object and Function, will you be able to extend the functionality of JavaScript? Woolen cloth?
So, congratulations, you got it!
Today, with the rapid development of AJAX technology, the JavaScript runtime libraries of many successful AJAX projects have greatly expanded the prototype functions of built-in functions. For example, Microsoft's ASP.NET AJAX adds a large number of new features to these built-in functions and their prototypes, thus enhancing the functionality of JavaScript.
Let’s look at a piece of code excerpted from MicrosoftAjax.debug.js:
String.prototype.trim = function String$trim() {
if (arguments.length !== 0) throw Error.parameterCount();
return this.replace(/^s+|s+$/g, '');
}
This code extends a trim method to the prototype of the built-in String function, so all String class objects have a trim method. With this extension, in the future, if you want to remove the whitespace between two sections of a string, you no longer need to process it separately, because any string has this extension function, and you only need to call it, which is really convenient.
Of course, few people add methods to the prototype of Object, because that will affect all objects, unless this method is indeed required by all objects in your architecture.
Two years ago, in the early days of designing the AJAX class library, Microsoft used a technology called "closure" to simulate "classes". The approximate model is as follows:
function Person(firstName, lastName, age)
{
//Private variables:
var _firstName = firstName;
var _lastName = lastName;
age;
alert("Hello, I'm " + firstName + "" " + LastName);
};
};
Var Billgates = New Person (" Bill "," Gates ", 53);
Var Stevejobs = New Person (" Steve "," Jobs ", 53) ;
BillGates.SayHello();
SteveJobs.SayHello();
alert(BillGates.getName() + " " + BillGates.age);
alert(BillGates.firstName); //Private variables cannot be accessed here
It is obvious that the class description of this model is particularly similar to the description form of C# language. Private members, public properties and available methods are successively defined in a constructor, which is very elegant. In particular, the "closure" mechanism can simulate the protection mechanism of private members, which is very beautiful.
The so-called "closure" is to define another function in the constructor body as the method function of the target object, and the method function of this object in turn refers to the temporary variable in the outer outer function body. This allows the temporary variable values used by the original constructor body to be indirectly maintained as long as the target object can always maintain its methods during its lifetime. Although the initial constructor call has ended and the name of the temporary variable has disappeared, the value of the variable can always be referenced within the method of the target object, and the value can only be accessed through this method. Even if the same constructor is called again, only new objects and methods will be generated, and the new temporary variables only correspond to new values, which are independent from the last call. Very clever indeed!
But as we said before, setting a method for each object is a big waste. In addition, "closure", a mechanism that indirectly maintains variable values, often creates problems for JavaScript's garbage collector. Especially when encountering complex circular references between objects, the judgment logic of garbage collection is very complicated. Coincidentally, early versions of IE browser did have memory leak problems in JavaScript garbage collection. Coupled with the poor performance of the "closure" model in performance testing, Microsoft eventually abandoned the "closure" model and switched to the "prototype" model. As the saying goes, "Everything you gain must come with a loss."
The prototype model requires a constructor to define the members of the object, but the method is attached to the prototype of the constructor. The rough writing is as follows:
//Define the constructor
function Person(name)
{
this.name = name; //Define members in the constructor };
//The method is defined on the prototype of the constructor
Person .prototype.Sayhello = Function () {
Alert ("Hello, I'm" + this.Name); Then, then call(this, name); //Call the upper constructor
this.salary = salary; //Extended members
};
//The subclass constructor first needs to use the upper constructor to create the prototype object and implement inheritance Concept
Employee.prototype = new Person() //Only the methods of its prototype are needed, the members of this object have no meaning!类 子 // The subclass method is also defined on the constructor
employee.prototype.showmetheMoney = function () {
alert (this.Name + "$" + this.salary); Gates = new Person("Bill Gates");
BillGates.SayHello();
var SteveJobs = new Employee("Steve Jobs", 1234);
SteveJobs.SayHello();
SteveJobs.ShowMeTheMoney();
Prototype Class Model Although it cannot simulate real private variables, and the class must be defined in two parts, it does not seem very "elegant". However, methods are shared between objects, do not encounter garbage collection problems, and perform better than the "closure" model. As the saying goes, "Everything you lose must have a gain."
In the prototype model, in order to implement class inheritance, the prototype of the subclass constructor must first be set to an object instance of the parent class. The purpose of creating this parent class object instance is to form a prototype chain to share the upper prototype method. But when this instance object is created, the upper-level constructor will also set object members to it. These object members are meaningless for inheritance. Although we did not pass parameters to the constructor, we did create a number of useless members, although their values are undefined, which is also a waste.
Alas! Nothing is perfect in the world!
The True Truth of the Archetype
Just when we were overwhelmed with emotion, a red light flashed in the sky, and Guanyin Bodhisattva appeared in the auspicious clouds. I saw her holding a jade purification bottle, flicking the green willow branches, and sprinkling a few drops of nectar, which immediately gave JavaScript a new aura.
The nectar sprinkled by Guanyin condensed into blocks in the JavaScript world and became something called "grammatical nectar". This syntactic nectar can make the code we write look more like an object language.
If you want to know what this "grammatical nectar" is, please listen carefully.
Before understanding these grammatical nectar, we need to review the process of constructing objects in JavaScript.
We already know that the process of creating an object in the form of var anObject = new aFunction() can actually be divided into three steps: the first step is to create a new object; the second step is to set the built-in prototype object of the object as the constructor The prototype object referenced by prototype; the third step is to call the constructor using the object as this parameter to complete initialization work such as member setting. After the object is created, any access and operation on the object are only related to the object itself and the string of objects on the prototype chain, and have nothing to do with the constructor. In other words, the constructor only plays the role of introducing the prototype object and initializing the object when creating the object.
So, can we define an object ourselves as a prototype, describe the class on this prototype, and then set this prototype to the newly created object and treat it as the class of the object? Can we use a method in this prototype as a constructor to initialize the newly created object? For example, we define such a prototype object:
var Person = //Define an object as a prototype class
{
Create: function(name, age) //This is the constructor
.age = age;
},
,,
{T alert (this.name + "is" + this.age + "" year old. ");
}}};
how much is this JSON form like a C#class! There are both constructors and various methods. If you can create an object in some form and set the object's built-in prototype to the "class" object above, wouldn't it be equivalent to creating an object of that class?
But unfortunately, we can hardly access the prototype properties built into the object! Although some browsers can access the object's built-in prototype, doing so only restricts the browser to which the user must use. This is also almost impossible.
So, can we use a function object as a medium, use the prototype attribute of the function object to transfer the prototype, and use the new operator to pass it to the newly created object?
In fact, code like this can achieve this goal:
function anyfunc(){}; //Define a function shell
anyfunc.prototype = Person; //Put the prototype object into the transfer station prototype