JavaScript scope and variable elevation

Source: Internet
Author: User

What is the result of the following program?

[JavaScript]View PlainCopy
    1. var foo = 1;
    2. function Bar () {
    3. if (!foo) {
    4. var foo = 10;
    5. }
    6. Alert (foo);
    7. }
    8. Bar ();

The result is 10;

What about the following one?

[JavaScript]View PlainCopy
    1. var a = 1;
    2. Function B () {
    3. A = 10;
    4. return;
    5. function A () {}
    6. }
    7. b ();
    8. alert (a);

The result is 1.

You're a surprise, aren't you? What's going on? This may be unfamiliar, dangerous, confusing, and, in fact, very useful and impressive JavaScript language features. I don't know if there is a standard name for this behavior, but I like the term: "Hoisting (variable Promotion)". This article will give a brief explanation of this mechanism, but first let's have some necessary understanding of the scope of JavaScript.

Scope of JavaScript

For JavaScript beginners, one of the most confusing places is the scope; in fact, not only beginners. I've seen some experienced JavaScript programmers, but they don't understand scope deeply. The JavaScript scope is confusing because its program syntax itself is long like the C-family language, like the following C program:

[CPP]View PlainCopy
  1. #include <stdio.h>
  2. int main () {
  3. int x = 1;
  4. printf ("%d,", x); //1
  5. if (1) {
  6. int x = 2;
  7. printf ("%d,", x); //2
  8. }
  9. printf ("%d\n", X); //1
  10. }

The output is 1 2 1, because the C family language has a block scope, when the program control walks into a block, such as if block, only the variables that act on the block can be declared without affecting the scope outside the block. But in JavaScript, it doesn't work. Take a look at the following code:

[JavaScript]View PlainCopy
    1. var x = 1;
    2. Console.log (x); //1
    3. if (true) {
    4. var x = 2;
    5. Console.log (x); //2
    6. }
    7. Console.log (x); //2

The result would be 1 2 2. Because JavaScript is a function scope. This is the biggest difference from the C family language. The If inside the program does not create a new scope.

For many C,c++,java programmers, this is not what they expect and welcome. Fortunately, based on the flexibility of JavaScript functions, there is a flexible place to be. If you have to create a temporary scope, you can do the following:

[JavaScript]View PlainCopy
  1. function foo () {
  2. var x = 1;
  3. if (x) {
  4. (function () {
  5. var x = 2;
  6. //Some other code
  7. }());
  8. }
  9. //X is still 1.
  10. }

This method is flexible and can be used wherever you want to create temporary scopes. Not only in the block. However, I highly recommend that you take some time to understand the scope of JavaScript. It's very useful and is one of my favorite JavaScript features. If you understand the scope, then the variable promotion is more meaningful to you.

variable declaration, naming, and elevation

In JavaScript, variables come into scope in 4 basic ways:

    • 1 language built-in: All scopes have this and arguments; ( translator Note: Tested arguments in global scope is not visible)
    • 2 Formal parameters: the formal parameters of the function as part of the function body scope;
    • 3 function declaration: As in this form: function foo () {};
    • 4 variable declaration: like this: Var foo;

function declarations and variable declarations are always silently "lifted" by the interpreter to the topmost part of the method body. This means, like the following code:

[JavaScript]View PlainCopy
    1. function foo () {
    2. Bar ();
    3. var x = 1;
    4. }

Will actually be interpreted as:

[JavaScript]View PlainCopy
    1. function foo () {
    2. var x;
    3. Bar ();
    4. x = 1;
    5. }

Whether or not the block defining the variable can be executed. The following two functions are actually the same thing:

[JavaScript]View PlainCopy
  1. function foo () {
  2. if (false) {
  3. var x = 1;
  4. }
  5. return;
  6. var y = 1;
  7. }
  8. function foo () {
  9. var x, y;
  10. if (false) {
  11. x = 1;
  12. }
  13. return;
  14. y = 1;
  15. }

Note that the variable assignment is not promoted, only that the declaration has been promoted. However, the function declaration is a little different, and the function body is promoted together. Note, however, that there are two ways to declare a function:

[JavaScript]View PlainCopy
  1. function Test () {
  2. Foo (); //TypeError "Foo is not a function"
  3. Bar ();  //"This would run!"
  4. var foo = function () { //variable pointing to a functional expression
  5. Alert ("This won ' t run!");
  6. }
  7. Functions Bar () { //function declaration function named Bar
  8. Alert ("This would run!");
  9. }
  10. }
  11. Test ();

In this example, only functional declarations are promoted along with the function body. Foo's declaration is promoted, but the function it points to is only assigned when it is executed.

The above-mentioned things cover some of the basics of ascension, and they don't seem so confused. However, in some special scenarios, there is a certain degree of complexity.

Variable parsing order

The most necessary thing to keep in mind is the sequence of variable parsing. Remember the 4 ways I gave the name to enter the scope? The order in which the variables are parsed is the order in which I list them. In General, if a name is already defined, it will not be overridden by another property of the same name. This is to say that(the translator does not understand this sentence, so first delete style) The declaration of the function has a higher precedence than the declaration of the variable . This is not to say that assigning a value to that variable is not a matter of use, but rather that the declaration is not ignored. (Translator Note: The declaration of a function is a higher priority than the declaration of a variable, and the following program can help you understand)

[JavaScript]View PlainCopy
  1. <script>
  2. function A () {
  3. }
  4. var A;
  5. alert (a); //Print out the function body of a
  6. </script>
  7. <script>
  8. var A;
  9. function A () {
  10. }
  11. alert (a); //Print out the function body of a
  12. </script>
  13. But be aware of the difference between the following two words:
  14. <script>
  15. var a=1;
  16. function A () {
  17. }
  18. alert (a); //Print out 1
  19. </script>
  20. <script>
  21. function A () {
  22. }
  23. var a=1;
  24. alert (a); //Print out 1
  25. </script>


Here are 3 exceptions:
1 built-in name arguments is acting strangely, he looks like it should be declared after the function form argument, but before the function declaration. This means that if there is arguments in the parameter, it will have precedence over the built-in one. This is a very bad feature, so to eliminate the use of arguments in formal parameters;
2 Defining this variable anywhere will be a syntax error, which is a good feature;
3 If more than one form parameter has the same name, the last one has a priority, even though the value is undefined when actually running;

Named functions

You can give a function a name. If so, it is not a function declaration, at the same time, the function body definition inside the specified function name ( if any, such as the following spam, the translator note) will not be promoted, but ignored. Here are some code to help you understand:

[JavaScript]View PlainCopy
  1. Foo (); //TypeError "Foo is not a function"
  2. Bar (); //Valid
  3. Baz (); //TypeError "Baz is not a function"
  4. Spam (); //Referenceerror "spam is not defined"
  5. var foo = function () {}; //Foo points to anonymous functions
  6. function bar () {}; //Function declaration
  7. var baz = function spam () {};  //Name function, only Baz is promoted, spam will not be promoted.
  8. Foo (); //Valid
  9. Bar (); //Valid
  10. Baz (); //Valid
  11. Spam (); //Referenceerror "spam is not defined"
How to write code

Now that you understand scope and variable elevation, what does this mean for JavaScript coding? The most important thing is that you always define your variables with var. And I highly recommend that for a name, there is always only one var declaration in a scope. If you do this, you will not encounter scope and variable elevation issues.

How to say the language specification

I find ECMAScript reference documentation always useful. Here's what I found about scopes and variable promotion:
If a variable is declared in a function body class, it is a function scope. Otherwise, it is the global scope (as a property of global). The variable will be created when execution enters the scope. Blocks do not define new scopes, only function declarations and programs ( which the translator thinks is the global nature of code Execution) create new scopes. Variables are initialized to undefined when they are created. If a variable declaration statement has an assignment operation, the assignment will occur only when it is executed, not when it is created.

I expect this article to bring a glimmer of light to programmers who are more confused with JavaScript. I myself do my best to avoid bringing more confusion. If I say something wrong, or ignore something, please let me know.

Translator Supplement

xu281828044 reminds me of the promotion of named functions under the global scope under IE:
I did this test when I translated the article:

[HTML]View PlainCopy
    1. <script>
    2. Functiont () {
    3. Spam ();
    4. var baz = function spam () {alert (' This is spam ')};
    5. }
    6. T ();
    7. </Script>

This notation, the promotion of a named function under a non-global scope, behaves consistently under IE and ff. I changed it to:

[HTML]View PlainCopy
    1. <script>
    2. Spam ();
    3. var baz = function spam () {alert (' This is spam ')};
    4. </Script>

IE can be executed under the spam, FF can not. It shows that different browsers differ in handling this detail.

This question also led me to think of another 2 questions, 1: for the global role in the scope of variables, Var and no var are different. Without the notation of VAR, its variables will not be promoted. For example, the following two programs, the second will be an error:

[HTML]View PlainCopy
    1. <script>
    2. alert (a);
    3. var a=1;
    4. </Script>
[HTML]View PlainCopy
    1. <script>
    2. alert (a);
    3. A=1;
    4. </Script>

2: local variables created in Eval are not promoted (nor can it be done).

[HTML]View PlainCopy
    1. <script>
    2. var a = 1;
    3. function T () {
    4. alert (a);
    5. Eval (' var a = 2 ');
    6. alert (a);
    7. }
    8. T ();
    9. alert (a);
    10. </Script>


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

from:http://blog.csdn.net/sunxing007

JavaScript scope and variable elevation

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.