The scope of variables in JavaScript is described in detail

Source: Internet
Author: User
Tags function definition

The following variables have global scope:

1. All definitions in the outermost variable (non-function body part) have global scope.

2. A variable that does not define a direct assignment is declared as a global scope.

3. Properties of all window objects have global scope.


The following variables have function scopes


1. Variables defined within the function body with VAR, note here, as long as the variables defined in the function, even in the most

The last sentence defines that the variable also has the scope of the entire function. But its assignment is to wait until the code runs to the

After the!!! of the assigned value


In particular, it should be explained that the scope is a layer contains, the outermost is the global scope, which can contain function tuning

The question of the proposed

First look at an example:

var name = ' Laruence ';

function echo () {

alert (name);

var name = ' Eve ';

alert (name);

alert (age);

}

Echo ();< li>

What is the result of the operation?

The above question, I believe there will be many people will think is:

Laruence

Eve

[Script Error


Because the first alert in echo takes the value of the global variable name, and the second value is overwritten by the local variable name, the second alert is ' Eve '. The age attribute is not defined, so the script will make an error.

But in fact, the result of the operation should be:

Undefined

Eve

[Script Error


Why, then?


The scope chain of JavaScript

Let's first take a look at the scope principle of javasript (JS, which does not fully represent JScript): The JS authoritative guide has a very incisive description: "The functions in JavaScript run in their defined scopes, not in the scopes they are executed in."


The scope chain of JavaScript
First look at the following code:

View Plaincopy to Clipboardprint?
1.<script type= "Text/javascript" > var rain = 1; function Rainman () {var man = 2; function inner () {var innervar = 4; alert (rain);} inner ();//Call inner function} Rainman (); Call the Rainman function </script>
<script type= "Text/javascript" > var rain = 1; function Rainman () {var man = 2; function inner () {var innervar = 4; alert (rain);} inner ();//Call inner function} Rainman (); Call the Rainman function </script> observe alert (rain); JavaScript first looks in the inner function to see if the variable is defined rain, if it is defined, use the rain variable in the inner function, or if the rain variable is not defined in the inner function, JavaScript continues to look in the Rainman function to see if the rain variable is defined, in which the rain variable is not defined in the Rainman function body, and the JavaScript engine continues to look up (the global object) to see if it defines rain In the global object we defined rain = 1, so the end result would pop ' 1 '.

Scope chain: When JavaScript needs to query for a variable x, it first looks for the first object in the scope chain, and if the first object does not define an X variable, JavaScript continues to find that there are no X variables defined, and if the second object is undefined, it continues to find, and so on.

The above code involves three scope chain objects, followed by: Inner, Rainman, window.

For the next knowledge, you can understand smoothly, I remind again, in JS: "Everything is an object, function is also".

In JS, the concept of scope is similar to other languages, and each time a function is called, it goes into the scope of a function, which returns the scope of the call before it returns from the function.

JS's syntax style is similar to C + +, but the scope implementation is different from C + +, instead of using a "stack" approach, it uses a list, which is as follows (as described in ECMA262):
The scope of any execution context moment is implemented by the scope chain (scope chain, described later).
When a function is defined, it defines the scope chain of the moment to link to the [[scope]] property of the function object.
When a function object is called, the creates an active object (that is, an object), and then, for each function's formal parameters, is named the active object's named property, and then the active object is the front end of the scope chain (scope chain) of the function object, and the Scope]] is added to the scope chain.

Look at an example:

var func = function (LPs, RPS) {

var name = ' Laruence ';

........

}

Func ();< li>

When executing a FUNC definition statement, a function object's [[Scope]] Property (internal property, which only the JS engine can access, but several Firefox engines (SpiderMonkey and Rhino) provides a private property __parent__ to access it and link this [[scope]] property to the scope chain that defines it (detailed later), because Func is defined in the global environment, so [[scope]] simply points to the global Active object window active objects at this time.

When Func is invoked, an active object is created (assumed to be aobj, created by the JS engine precompiled moment, described later), and the Arguments property is created, and then two named attributes are added to the object aobj.lps, Aobj.rps; For each local variable and function definition declared in this function, a named property with the same name as the active object.

The invocation parameter is then assigned to the parameter, and the value is undefined for the missing invocation parameter.

The active object is then made the front end of the scope chain, and the top-level active object that is func by the [[scope] property] is defined to add to the scope chain.

With the above scope chain, when identifier resolution occurs, the properties of each active object in the current scope chain list are queried, and returned if the name is found. Not found, that is, this identifier is not defined.

Note that because the [[scope] property of a function object is determined when defining a function, not when it is invoked, as in the following example:

var name = ' Laruence ';

function echo () {

alert (name);

}

function env () {

var name = ' Eve ';

Echo ();

}

Env ();< li>


The results of the operation are:

Laruenc


With the above knowledge, let's take a look at the following example:

function Factory () {

var name = ' Laruence ';

var intro = function () {

Alert (' I am ' + name);

}

return intro;

}

function app (para) {

var name = para;

var func = factory ();

Func ();

}

App (' Eve ');< li>


When invoking the app, the scope chain is made up of: {Window Activity Object (global)}->{app active object}.

When you first enter the app function body, the app's active object has a arguments attribute with two values of undefined properties: Name and Func. and a property para with a value of ' Eve ';

The scope chain at this point are as follows:

[[scope chain]] = [

{

Para: ' Eve ',

Name:undefined,

Func:undefined,

Arguments: []

}, {

Window Call Object

}

]< li>


When the call enters the factory function body, the scope of the factory at this time is chain:

[[scope chain]] = [

{

Name:undefined,

intor:undefined

}, {

Window Call Object

}

]< li>


Notice that the active object of the app is not included in the scope chain at this time.

When defining the intro function, the [[scope]] of the intro function is:

[[scope chain]] = [

{

Name: ' Laruence ',

intor:undefined

}, {

Window Call Object

}

]< li>


After returning from the factory function, an identifier resolution occurs when Intor is invoked in the app body, and the Sope chain at this time is:

[[scope chain]] = [

{

Intro Call Object

}, {

Name: ' Laruence ',

intor:undefined

}, {

Window Call Object

}

]< li>


Because the scope chain does not contain factory active objects. Therefore, the result of the name identifier resolution should be the name attribute in the factory active object, which is ' laruence '.

So the results of the operation are:

I am Laruenc

Now, you're going to run the functions in JavaScript in their defined scopes, not the scopes they're being executed. This sentence, should have a comprehensive understanding of it?

Pre-compiling JavaScript

We all know that JS is a scripting language, JS implementation process, is a process of translation execution.
Then JS implementation, there is no similar process of compiling it?

First, let's look at an example:

<script>

Alert (typeof Eve); function

Function Eve () {

Alert (' I am laruence ');

};

</script>< li>

Eh? Is eve not supposed or undefined at alert? What is the type of Eve or function?

Well, yes, in JS, there is a precompiled process, JS in the execution of each section of JS code, will first deal with the VAR keyword and function definitions (function definitions and functional expressions).
As stated above, before calling the function execution, you first create an active object, then search for the local variable definition in the function, and the function definition, and make the variable name and function names the same as the active object, and for local variables, the value of the variable will be computed when it is actually executed. This is simply a undefined.

And for the definition of a function, is a place to note:

<script>

Alert (typeof Eve); Result: function

Alert (typeof Walle); Result: undefined

Function Eve () {//functions definition

Alert (' I am laruence ');

};

var Walle = function () {//functions expression

}

Alert (typeof Walle); Result: function

</script>< li>


This is the difference between a function definition and a function expression, and for a function definition, the function definition is advanced. A function expression, however, is evaluated during execution.

Speaking of which, by the way, a question:

var name = ' Laruence ';

Age = 26;< li>

We all know that we do not use the var keyword to define a variable, which is equivalent to a global variable, to contact our knowledge just now:

When parsing an identifier for age, because it is a write operation, the identifier is not found when the global window activity object is found, and a value of undefined is returned on the basis of the window activity object.

In other words, the age is defined in the top-level scope.

Now, perhaps you have noticed what I just said: JS in the execution of each section of JS code.
Yes, let's take a look at the following example:

<script>

Alert (typeof Eve); Result: undefined

</script>

<script>

Function Eve () {

Alert (' I am laruence ');

}

</script>< li>

You get it? That is, the pre-compilation of JS is in the field of processing units ...

Uncover the answer

Now let's go back to our first question:

When the Echo function is invoked, the active object of ECHO is already created by the precompiled process, at which point the active object of ECHO is:

[Callobj] = {

name:undefined

}< li>


When an identifier resolution occurs at the first alert, the Name property is found in the active object of ECHO, so this name property completely masks the name attribute in the global active object.

Related Article

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.