I have read many introductionsJavascriptThe article on object-oriented technology is dizzy. Why? It's not because it's not well written, but because it's too esoteric. The objects in javascript haven't clearly explained what's going on. As soon as they come up, they go straight to the topic, class/Inheritance/prototype/private variable. As a result, after reading it for a long time, I had a rough understanding and had a good aftertaste. It seems that I did not understand anything.
This article is written in chapter 7, 8 and 9 of <javascript-the definitive guide, 5th edition>, I will try to describe the javascript object-oriented technology (Object/array-> function --> class/constructor/prototype) according to the structure of the original book ). I will attach the original English statement for your reference.
Scope, closure, simulate private attributes
Let's take a brief look at the variable scope. We are familiar with these things, so we will not discuss them in detail.
Js Code
- Var sco = "global"; // global variable
- Function t (){
- Var sco = "local"; // local variable inside the Function
- Alert (sco); // The local variable is preferentially called.
- }
- T (); // local
- Alert (sco); // global cannot use local variables in the function
Note that there is no block-level scope in javascript, that is, in java or c/c ++, we can use "{}" to enclose a block, to define local variables in the block, these variables do not work outside the "{}" block. At the same time, you can also define local variables in control statements such as the for loop, however, this feature is not available in javascript:
Js Code
- Function f (props ){
- For (var I = 0; I <10; I ++ ){}
- Alert (I); // 10 although I is defined in the control statement of the for loop
- // Other locations can still access the variable.
- If (props = "local "){
- Var sco = "local ";
- Alert (sco );
- }
- Alert (sco); // Similarly, the function can still reference the variables defined in the if statement.
- }
- F ("local"); // 10 local
Be careful when defining local variables in the function:
Js Code
- var sco = "global";
- function print1() {
- alert(sco); //global
- }
- function print2() {
- var sco = "local";
- alert(sco); //local
- }
- function print3() {
- alert(sco); //undefined
- var sco = "local";
- alert(sco); local
- }
- print1(); //global
- print2(); //local
- print3(); //undefined local
The first two functions are easy to understand. The key is the third: the first alert statement does not display the global variable, but undefined, because in the print3 function, we have defined the sco local variable (no matter where it is located), so the global sco attribute does not work within the function. Therefore, in the first alert, sco is actually a local sco variable, which is equivalent:
Js Code
- function print3() {
- var sco;
- alert(sco);
- sco = "local";
- alert(sco);
- }
From this example, we can see that when defining a local variable in a function, it is best to define the required variable at the beginning to avoid errors.
The function scope has been determined when defining the function. For example:
Js Code
- Var scope = "global" // define global variables
- Function print (){
- Alert (scope );
- }
- Function change (){
- Var scope = "local"; // defines local variables
- Print (); // although the print function is called within the scope of the change function,
- // But the print function still works according to the scope defined by it during execution
- }
- Change (); // golbal
Closure
Closures are expressions with variables, code, and scopes. in javascript, a function is the combination of variables, code, and function scopes, therefore, all functions are closures (JavaScript functions are a combination of code to be executed and the scope in which toexecute them. this combination of code and scope is known as a closure in the computer science literature. all JavaScript functions are closures ). it seems quite simple.
But what is the function of a closure? Let's look at an example.
We want to write a method and get an integer every time. This integer is incremented by 1 each time. If you don't think about it, write it immediately:
Js Code
- var i = 0;
- function getNext() {
- i++;
- return i;
- }
- alert(getNext()); //1
- alert(getNext()); //2
- alert(getNext()); //3
Always use the getNext function to get the next integer, And then accidentally or intentionally set the value of global variable I to 0, and then call getNext again, you will find that starting from 1 again ........ at this time, you will think that it would be nice to set I as a private variable, so that it can be changed only within the method, and there is no way to modify it outside of the function. the following code is done according to this requirement. We will discuss it in detail later.
For ease of interpretation, we call the following code demo1.
Js Code
- function temp() {
- var i = 0;
- function b() {
- return ++i;
- }
- return b;
- }
- var getNext = temp();
- alert(getNext()); //1
- alert(getNext()); //2
- alert(getNext()); //3
- alert(getNext()); //4
Because the vast majority of javascript we usually call is under the client (browser), it is no exception here. When the javascript interpreter is started, a global object is created first, that is, the object referenced by "window. then all the global attributes and methods we define will become the attributes of this object. different functions and variables have different scopes, thus forming a scope chain ).
Obviously, when the javascript interpreter is started, this scope chain has only one Object: window (Window object, that is, global Object ). in demo1, the temp function is a global function. Therefore, the scope chain corresponding to the scope (scopr) of the temp () function is the scope chain when the js interpreter is started. There is only one window object.
When temp is executed, create a call object (activity object) and add the call object to the beginning of the scope chain corresponding to the temp function () the scope chain corresponding to the function contains two objects: The call object corresponding to the window object and the temp function (the activity object ). then, because we define variable I in the temp function and function B (), these will become the properties of the call object. Before that, the arguments attribute will be added to the call object to save the parameters passed during the execution of the temp () function. The entire scope chain is shown in:
Similarly, we can obtain the entire scope chain during function B () execution:
Note that in the scope chain of B (), the call object corresponding to function B () has only one arguemcnt attribute and does not have an I attribute. This is because in the definition of B, I attributes are not declared using the var keyword. Only attributes declared using the var keyword are added to the corresponding call object.
When the function is executed, first check whether the corresponding call object has any required properties. If not, search for the next level until it is found. If not, undefined is returned.
Now let's look at the execution of demo1. We use getNext to reference the temp function, while the temp function returns function B, so that the getNext function is actually a reference of function B.
If you execute one getNext operation, the B () function is executed. Because the scope of function B () depends on the function temp, the temp function will always exist in the memory. When function B is executed, it first looks for I and does not exist in the call object corresponding to function B. So it looks for it at the upper level and finds it in the call object corresponding to the temp function, then add the value to 1 and return this value.
In this way, as long as the getNext function is valid, the B () function will always be valid. At the same time, the temp function dependent on the B () function will not disappear, and the variable I will not disappear, in addition, this variable cannot be accessed outside the temp function. It can only be accessed inside the temp () function (B can of course ).
Let's look at an example of using closures to simulate private attributes:
Js Code
- Function Person (name, age ){
- This. getName = function () {return name ;};
- This. setName = function (newName) {name = newName ;};
- This. getAge = function () {return age ;};
- This. setAge = function (newAge) {age = newAge ;};
- }
- Var p1 = new Person ("sdcyst", 3 );
- Alert (p1.getName (); // sdcyst
- Alert (p1.name); // undefined because Person ('class') has no name attribute
- P1.name = "mypara" // Add the name attribute to p1 displayed
- Alert (p1.getName (); // sdcyst but does not change the return value of the getName Method
- Alert (p1.name); // mypara displays the name attribute of the p1 object
- P1.setName ("sss"); // change the private "name" attribute
- Alert (p1.getName (); // sss
- Alert (p1.name); // still mypara
Defines a Person class, which has two private attributes: name and age. They define the corresponding get/set methods respectively. Although the name and age attributes of p1 can be displayed, this display setting does not change the "name/age" private attribute we simulated at the initial design.
It is not easy to explain the closure. Many people on the Internet also use examples to illustrate the closure. If something is wrong, correct it.