JavaScript scopes and declarations promote "translation"

Source: Internet
Author: User

Original link: http://www.adequatelygood.com/JavaScript-Scoping-and-Hoisting.html

JavaScript scopes and Declaration elevation

Do you know the value of alert after JavaScript is executed?

1 var foo = 1; 2 function Bar () {3     if (! foo) {4         var foo = ten; 5     }6    alert (foo); 7 }8 Bar ();

If you are surprised by the result of "10", then you may need to take a good look at this article:

1 var a = 1; 2 function B () {3     a = ten; 4     return ; 5     function A () {} 6 }7B (); 8 alert (a);

What about this one? The browser will alert to "1", so what are the results? It's true that these look a bit strange, dangerous, and confusing, but that's exactly how JavaScript is a powerful and expressive language. I don't know the standard name for this feature, but I'm used to calling it "ascension," and this article will try to clarify the mechanism, but first we need to understand the scope of JavaScript.

Scope of JavaScript

Many beginners are most likely to confuse the "scope", in fact, it is not only beginner easy to confuse, I have seen many experienced JavaScript programmers do not fully understand the "scope." The scope of JavaScript is not clear because it is understood as the scope of the Class C language. Consider the following C program:

1#include <stdio.h>2 intMain () {3     intx =1;4printf"%d,", x);//15     if(1) {6         intx =2;7printf"%d,", x);//28     }9printf"%d\n", x);//1Ten}

The output of this program is 1,2,1. This is because C, and Class C languages have block-level scopes. The contemporary code executes inside a block, such as a pair of curly braces, where the new variable is declared within the scope and does not affect the outside of the curly brace. This is different from JavaScript. Try the following code under Firebug:

 1  var  x = 1  2  console.log (x); //  1  3   True   4  var  x = 2;  5  console.log (x); //  2  6   7  console.log (x); //  

In this case, Firebug will show 1,2,2. This is because JavaScript is a function scope, which is completely different from the block level of the C language, such as in curly braces, which does not create a new scope. Only the function will be.

Many languages use block-level scopes, such as c,c++,c#, and Java, so it's easy for programmers who just learn JavaScript to understand that, fortunately, JavaScript's function definitions are very flexible, and if the inverse needs to create a temporary scope within a function, You can do this:

1 functionfoo () {2     varx = 1;3     if(x) {4(function () {5             varx = 2;6             //Some other code7         }());8     }9     //x is still 1.Ten}
declaring variables and lifting

In JavaScript, there are four basic ways a variable enters a scope:

    1. language definition: the global scope, by default, has the variable this and arguments.
    2. formal parameter: a function can be a tangible parameter, and its scope is the entire function.
    3. function declaration: For example this form function foo () {}
    4. Variable declaration : For example, this form of Var foo;

function declarations and variable declarations are internally "lifted" when parsing a JavaScript program, formal parameters and global variables already exist, meaning that the 3 and 42 variable types are promoted, meaning the code will look like this after parsing:

  1  function   Foo () {  2   bar ();   var  x = 1   "   5 The  is actually interpreted like this:  6   7  function   Foo () {  8  var   X;    bar ();  10  x = 1;  11 } 

It turns out that it exists regardless of whether it contains a variable declaration. The following two functions are equivalent:

1 functionfoo () {2     if(false) {3         varx = 1;4     }5     return;6     vary = 1;7 }8 functionfoo () {9     varx, y;Ten     if(false) { Onex = 1; A     } -     return; -y = 1; the}

Note: When a function is declared as a value of a variable, the declaration is not promoted, in which case only the variable name is promoted, which causes the function name to be promoted, but the function body is not promoted, but remember that the function declaration has two forms, consider the following javascript:

1 functionTest () {2Foo ();//TypeError "Foo is not a function"3Bar ();//"This would run!"4     varFoo =function() {//function expression assigned to local variable ' foo '5Alert ("This won ' t run!");6     }7     functionBar () {//function declaration, given the name ' bar '8Alert ("This would run!");9     }Ten } OneTest ();

In this example, only the function declaration that contains the function body is promoted to the top, and the variable "foo" is promoted, but its body is on the right, and it is assigned only when the statement is executed.

This is the basic concept of ascension, so it does not seem so complicated and confusing. Of course, when writing JavaScript, there are some special situations that can be slightly more complicated.

Variable Name resolution ORDER

The most important thing is to remember the variable name resolution order in special cases. There are four ways to enter the namespace, which is based on the list from the top to the next, the order list is listed below, in general, if a name has been defined, then it will not be overridden by another name, which means that a function declaration takes precedence over the variable declaration, This is not equal to assigning a new named invalid, except that the declaration will be masked. They also have some exceptions:

    • The weird case of the built-in arguments, which looks like the formal parameter has been declared before the function declaration, means that a formal parameter name arguments will take precedence over the built-in arguments, even if it is not defined, which is a bad feature. Do not use arguments as a formal parameter.
    • If you define this name in some places, it can cause syntax errors. This is a good feature.
    • If more than one parameter has the same name, the last name in the formal parameter will be given precedence, even if it is not defined.
Function-Named expressions

You can assign a function definition to a function name in the form of a function expression, which is like a function definition, but it differs from a function declaration, which does not enter the scope and the function body is not promoted. Here is some code as an example to illustrate its meaning:

1Foo ();//TypeError "Foo is not a function"2Bar ();//valid3Baz ();//TypeError "Baz is not a function"4Spam ();//referenceerror "spam is not defined"5 6 varFoo =function() {};//anonymous function expression (' foo ' gets hoisted)7 functionBar () {};//function declaration (' Bar ' and the function body get hoisted)8 varBaz =functionSpam () {};//named function expression (only ' Baz ' gets hoisted)9 TenFoo ();//valid OneBar ();//valid ABaz ();//valid -Spam ();//referenceerror "spam is not defined"
How to use this knowledge to write code

Now that you know the scope and naming promotion, how do you write JavaScript code? A very important thing is to use Var when declaring variables. I strongly recommend that you use Var to define variables at the head of each scope, and if you always do, you will not be confused by the nature of the ascension. However, it is difficult to distinguish between the actual declared variables under the current scope and the variables that are present. I recommend using JSLint's Onevar option to perform these. If you are prepared to do so, your code should look like this:

1 /*  */2function  foo (A, B, c) {3     var x = 1, 4         Bar,5         baz = "something"; 6 }
What does the spec say?

I find it useful to review ECMAScript Starndard frequently to understand how these features work. Here is the description of the variable declaration and scope (the latest version of 12.2.2 part)

If a variable is declared inside a function declaration, then the variable is defined within the current function scope, as described in section 10.1.3. In addition, they are defined in the global scope (that is, they are created as members of global objects, as described by 10.1.3), and have attribute attributes. Variables are created within the scope of the current execution, and a block does not produce a new function space, and only the program and function declarations produce new spaces. When a variable is initialized, it is created as a undefined. A variable is actually initialized by assigning an existing value to the variable using an expression. Not when a variable is created.

I hope this article explains some of the confusing features in JavaScript code. I am trying to explain these issues comprehensively, to avoid creating new problems, if there is more confusion, if I turn over any errors or major omissions, please let me know.

JavaScript scopes and declarations promote "translation"

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.