Javascript Scope Principle

Source: Internet
Author: User

Source: http://www.laruence.com/2009/05/28/863.html

Question proposal

First, let's look at an example:
VaR name = 'laruence ';
Function echo (){
Alert (name );
VaR name = 'Eve ';
Alert (name );
Alert (AGE );
}
Echo ();

What is the running result?

I believe many people will think of the problem as follows:
Laruence
Eve
[Script Error]

In ECHO, the value of the global variable name is obtained during the first alert operation, and the second value is overwritten by the local variable name. Therefore, the second alert operation is 'Eve '. the age attribute is not defined, so the script will fail.

However, the running result should be:
Undefined
Eve
[Script Error]

Why?
Javascript scope chain

First, let's take a look at the principle of the scope of javasript (JS for short, not entirely representative of JScript): The JS authoritative guide contains a very incisive description: "functions in Javascript run in their defined scopes, rather than in their executed scopes."

For the sake of your understanding, I would like to remind you that in JS, "Everything is an object and a function is also ".

In JS, the concept of scope is similar to that in other languages. Each time a function is called, it enters the scope of a function. After the function is returned, returns the scope before the call.

The syntax style of JS is similar to that of C/C ++, but the implementation of the scope is different from that of C/C ++. Instead of using the "stack" method, the list is used, the procedure is as follows (as described in ecma262 ):
The scope of any execution context is implemented by the scope chain.
When a function is defined, the scope chain of its definition time is linked to the [[Scope] attribute of this function object.
When a function object is called, an activity object (that is, an object) is created, and each function parameter is named as the name attribute of the activity object, then, this activity object is used as the frontend of the scope chain at this time, and the [[Scope] of this function object is added to the scope chain.

Let's look at an example:
VaR func = function (LPS, RPs ){
VaR name = 'laruence ';
........
}
Func ();

When executing the Definition Statement of func, a [[Scope] attribute (internal attribute, accessible only by the JS engine) of this function object will be created, but several Firefox engines (spidermonkey and rhino) provide the private attribute _ parent _ to access it), and set this [[Scope] attribute, link to the scope chain that defines it (which will be detailed later). Because func is defined in the global environment, [Scope] only points to the global activity Object window active object.

When calling func, an activity object will be created (assuming aobj is created at the JS engine pre-Compilation Time, which will be introduced later) and the arguments attribute will be created, then, two named attributes aobj will be added to this object. LPS, aobj. RPS; For each local variable and Function Definition declared in this function, it is used as the same name attribute of the activity object.

Then, assign the call parameter to the shape parameter. For the missing call parameter, assign the value to undefined.

Then, the activity object is used as the front-end of the scope chain, and the top-level activity object defined in func is pointed to by the [[Scope] attribute of func and added to scope China.

With the above scope chain, when the identifier is parsed, it will reverse query the attributes of each active object in the current scope chain list. If the same name is found, it will be returned. The identifier is not defined.

Note that because the [[Scope] attribute of a function object is determined when a function is defined, rather than called, The following example is shown:
VaR name = 'laruence ';
Function echo (){
Alert (name );
}
Function ENV (){
VaR name = 'Eve ';
Echo ();
}
ENV ();

The running result is:
Laruence

Based on 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 ');

When an app is called, scope chain is composed of: {window activity object (global)}-> {app activity object.

When you first enter the app function body, the app activity object has an arguments attribute. The two attributes with undefined values: Name and func. And a property with 'Eve;

The scope chain is as follows:
[[Scope chain] = [
{
Para: 'Eve ',
Name: undefined,
FUNC: undefined,
Arguments: []
},{
Window call object
}
]

When calling the function body that enters the factory, the scope chain of the factory is:
[[Scope chain] = [
{
Name: undefined,
Intor: Undefined
},{
Window call object
}
]

Note that the scope chain does not contain the activity object of the app.

When defining the intro function, the [[Scope] of the intro function is:
[[Scope chain] = [
{
Name: 'laruence ',
Intor: Undefined
},{
Window call object
}
]

After the return from the factory function, identifier parsing occurs when intor is called in the app body, and the sope chain at this time is:
[[Scope chain] = [
{
Intro call object
},{
Name: 'laruence ',
Intor: Undefined
},{
Window call object
}
]

Because the scope chain does not contain the factory activity object, the name identifier resolution result should be the name attribute in the factory activity object, that is, 'laruence '.

Therefore, the running result is:
I am laruence

Now, you should have a comprehensive understanding of "JavaScript Functions run in their defined scopes, rather than in their executed scopes?

Javascript pre-Compilation

As we all know, JS is a scripting language. js execution process is a process of translation execution.
Is there a similar compilation process in JS execution?

First, let's look at an example:
<SCRIPT>
Alert (typeof Eve); // Function
Function Eve (){
Alert ('I am laruence ');
};
</SCRIPT>

Eh? Shouldn't Eve be undefined during alert? How is the eve type or function?

Well, yes, in JS, there is a pre-compilation process. Before JS executes every piece of js code, the VaR keyword and Function Definition (Function Definition and function expression) are processed first ).
As mentioned above, before calling the function for execution, an activity object will be created first, and then the local variable definition in the function will be searched for, and the function definition, use both the variable name and function name as the property of the same name of the activity object. For the definition of a local variable, the value of the variable is calculated only when it is actually executed. In this case, it is simply assigned as undefined.

The definition of a function is important:
<SCRIPT>
Alert (typeof Eve); // result: Function
Alert (typeof walle); // result: Undefined
Function Eve () {// Function Definition
Alert ('I am laruence ');
};
VaR walle = function () {// function expression
}
Alert (typeof walle); // result: Function
</SCRIPT>

This is the difference between the function definition and the function expression. For the function definition, the function definition is advanced, and the function expression is calculated only during execution.

Here, by the way:
VaR name = 'laruence ';
Age = 26;

We all know that variables that are not defined using the VaR keyword are equivalent to global variables. We have just learned the following:

When parsing the age identifier, because it is a write operation, this identifier is not found when the global window activity object is found, returns an undefined age Attribute Based on the window activity object.

That is, age is defined in the top-level scope.

Now, you may have noticed that JS is executing every piece of JS Code ..
Right. Let's take a look at the following example:
<SCRIPT>
Alert (typeof Eve); // result: Undefined
</SCRIPT>
<SCRIPT>
Function Eve (){
Alert ('I am laruence ');
}
</SCRIPT>

Do you understand? That is, JS pre-compilation uses segments as the processing unit...

Uncover the mysteries

Now let's go back to our first question:

When the echo function is called, the ECHO activity object has been created during the pre-compilation process. At this time, the ECHO activity object is:
[Callobj] = {
Name: Undefined
}

During the first alert operation, the identifier is parsed and the name attribute is found in the ECHO activity object. Therefore, this attribute completely blocks the name attribute in the global activity object.

Now, do you understand?

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.