Basic of JavaScript object-oriented technology (6)

Source: Internet
Author: User

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
  1. VaRSCO ="Global";// Global variable
  2. FunctionT (){
  3. VaRSCO ="Local";// Local variables in the function
  4. Alert (SCO );// The local variable is preferentially called.
  5. }
  6. T ();// Local
  7. Alert (SCO );// Global cannot use local variables in the function
 
VaR SCO = "Global"; // global variable function T () {var SCO = "local"; // The local variable alert (SCO) inside the function ); // local preferentially calls the local variable} t (); // localalert (SCO); // global cannot use the local variable 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 and define local variables in the block. Outside the "{}" block, these variables no longer work,
At the same time, you can define local variables in control statements such as for loops, but this feature is not available in javascript:

JS Code
  1. FunctionF (props ){
  2. For(VaRI = 0; I <10; I ++ ){}
  3. Alert (I );// 10 although I is defined in the for loop control statement
  4. // Other locations can still access the variable.
  5. If(Props ="Local"){
  6. VaRSCO ="Local";
  7. Alert (SCO );
  8. }
  9. Alert (SCO );// Similarly, the function can still reference the variables defined in the IF statement.
  10. }
  11. F ("Local");// 10 local
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, the variable can still be accessed elsewhere in the function. if (props = "local") {var SCO = "local"; alert (SCO) ;}alert (SCO); // Similarly, the function can still reference the variable defined in the IF statement} f ("local"); // 10 local

 

Be careful when defining local variables in the function:

JS Code
  1. VaRSCO ="Global";
  2. FunctionPrint1 (){
  3. Alert (SCO );// Global
  4. }
  5. FunctionPrint2 (){
  6. VaRSCO ="Local";
  7. Alert (SCO );// Local
  8. }
  9. FunctionPrint3 (){
  10. Alert (SCO );// Undefined
  11. VaRSCO ="Local";
  12. Alert (SCO); Local
  13. }
  14. Print1 ();// Global
  15. Print2 ();// Local
  16. Print3 ();// Undefined local
 
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 (); // globalprint2 (); // localprint3 (); // 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,
It is undefined, because in the print3 function, we define the SCO local variable (no matter where the position is), then the global
The SCO attribute does not work within the function, so in the first alert, SCO is actually a local SCO variable, which is equivalent:

JS Code
    1. FunctionPrint3 (){
    2. VaRSCO;
    3. Alert (SCO );
    4. SCO ="Local";
    5. Alert (SCO );
    6. }
 
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
  1. VaRScope ="Global"// Define global variables
  2. FunctionPrint (){
  3. Alert (scope );
  4. }
  5. FunctionChange (){
  6. VaRScope ="Local";// Define local variables
  7. Print ();// Although the print function is called within the scope of the change function,
  8. // But the print function still works according to the scope defined by it during execution
  9. }
  10. Change ();// Golbal
VaR scope = "Global" // defines the global variable function print () {alert (scope);} Function Change () {var scope = "local "; // define the local variable 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
All functions are closures (JavaScript Functions are a combination of code to be executed and the scope in which
Execute 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 the 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
    1. VaRI = 0;
    2. FunctionGetnext (){
    3. I ++;
    4. ReturnI;
    5. }
    6. Alert (getnext ());// 1
    7. Alert (getnext ());// 2
    8. Alert (getnext ());// 3
 
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... you will think about how nice it is to set I to a private variable, so that it is only within the Method
It may be changed, 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
  1. FunctionTemp (){
  2. VaRI = 0;
  3. FunctionB (){
  4. Return++ I;
  5. }
  6. ReturnB;
  7. }
  8. VaRGetnext = temp ();
  9. Alert (getnext ());// 1
  10. Alert (getnext ());// 2
  11. Alert (getnext ());// 3
  12. Alert (getnext ());// 4
 
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. This is the temp () function.
The corresponding scope chain contains two objects: The call object corresponding to the window object and the temp function (the activity object). Then, because we define the variable I in the temp function,
Function B () is defined, which will become the property of the call object. Before that, add the arguments attribute to the call object.
The passed parameters. 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, the VaR keyword is not used.
Declare the I attribute. Only the attributes declared with 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, first find
I, it does not exist in the call object corresponding to B, so I searched for it at the upper level and found it in the call object corresponding to the temp function. So I added the value to 1 and then returned 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, and this variable is used in the temp function.
External access is not available at all. It can only be accessed within the temp () function (B is acceptable ).

Let's look at an example of using closures to simulate private attributes:

JS Code
  1. FunctionPerson (name, age ){
  2. This. Getname =Function(){ReturnName ;};
  3. This. Setname =Function(Newname) {name = newname ;};
  4. This. Getage =Function(){ReturnAge ;};
  5. This. Setage =Function(Newage) {age = newage ;};
  6. }
  7. VaRP1 =NewPerson ("Sdcyst", 3 );
  8. Alert (p1.getname ());// Sdcyst
  9. Alert (p1.name );// Undefined because person ('class') has no name attribute
  10. P1.name ="Mypara"// Add the name attribute to P1 displayed
  11. Alert (p1.getname ());// Sdcyst but does not change the return value of the getname Method
  12. Alert (p1.name );// Mypara displays the name attribute of the P1 object
  13. P1.setname ("Sss");// Change the private "name" attribute
  14. Alert (p1.getname ());// SSS
  15. Alert (p1.name );// Still mypara
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 ') no name attribute p1.name = "mypara" // Add the name attribute alert (p1.getname () to P1 displayed; // sdcyst does not change the returned value of the getname method alert (p1.name ); // mypara displays the name attribute p1.setname ("Sss") of the P1 object; // Changes 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, the display settings do not change.
The "Name/age" private property simulated at 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.

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.