javascript 作用域的一些小知识

首先,奉献两个题目

1.

 1 var foo = 1;
 2 function bar() {
 3     if (!foo) {
 4         var foo = 10;
 5     }
 6     console.log(foo); //返回10
 7 }
 8 bar();
 9 /****** 我是分割线******/
10 var foo = 1;
11 function bar() {
12     if (!foo) {
13         foo = 10;
14     }
15     console.log(foo); //返回1
16 }
17 bar();
18 
19 //why ?

Ctr +A 可以看答案哦~

why?先来看看一下ECMA上的描述

/*
 * If the variable statement occurs inside a FunctionDeclaration, 
 * the variables are defined with function-local scope in that function.
 * Otherwise, they are defined with global scope (that is, they are created as members of the global object.
 * 如果变量声明实在函数内部,那么变量定义的是函数的局部范围,否则它将作为一个全局变量
 * 
 * Variables are created when the execution scope is entered. 
 * A Block does not define a new execution scope. Only Program and FunctionDeclaration produce a new scope. 
 * Variables are initialised to undefined when created. 
 * A variable with an Initialiser is assigned the value of its AssignmentExpression when the VariableStatement 
  is executed, * not when the variable is created. * * 变量的创建发生在程序执行到那一步 * 一个语句块并不定义一个新的执行作用域,只有程序和函数声明产生作用域 * 变量初始化的时候被初始化为undefined * 当执行变量声明的时候 ,变量才会由表达式赋值,而并非在变量产生的时候就有 *
*/

看明白了没?

  总结:1.javascript 语言没有JAVA C++ 等块级作用域,if 判断,switch等不会使里面的声明的变量困在其中,而是作为块区域外的变量存在,只有函数声明产生新的作用域。

     2.变量的定义|初始化发生在进入程序但是还没执行前,变量初始化为undefined,当程序往下执行时,变量会被表达式赋值,这个时候变量采有值。

看代码,由此我们将上面的代码改成如下!

 1 var foo = 1;
 2 function bar() {
 3     var foo;    //undefined,先声明
 4     console.log(foo)
 5     if (!foo) {
 6         foo = 10;   //10
 7     }
 8     console.log(foo); //返回10
 9 }
10 bar();
11 //第二个
12 
13 var foo = 1;
14 function bar() {
15     console.log('foo',foo); //1 因为函数体内没有foo,这个时候通过作用域链获取window的foo 变量
16     if (!foo) {
17         foo = 10;
18     }
19     console.log(foo); //返回1
20 }
21 bar(); 

如何创建一个不影响其它程序的作用域呢,放在闭包内

 1 var foo = 1;
 2 function bar() {
 3     console.log("a",foo)
 4     if (foo) {
 5         (function(){
 6             var foo = 10;   //10
 7             console.log('foo',foo)
 8         })()
 9     }
10     console.log(foo); //返回1
11 }
12 bar();

在javascript中,一个名称进入作用域有四种基本方法( 作用域的提升)

 * Language-defined: All scopes are, by default, given the names this and arguments.
 * 语言本身所定义的
 * Formal parameters: Functions can have named formal parameters, 
 * which are scoped to the body of that function.
 * 函数参数
 * Function declarations: These are of the form function foo() {}.
 * 函数声明
 * Variable declarations: These take the form var foo;.
 * 变量声明
function test() {
    foo(); // TypeError "foo is not a function"
    bar(); // "this will run!"
    var foo = function () { // function expression assigned to local variable 'foo'
        alert("this won't run!");
    }
    function bar() { // function declaration, given the name 'bar'
        alert("this will run!");
    }
}
test();

  如上代码,foo 是没有被定义的,在表达式var foo = function(){} 之前,foo被“提升”到了前面,但是它的主体部份(赋值表达式)要等到执行到它才赋值,因此相当于被赋值为undefined,当执行到这个表达式时 ,它才被赋值为function,因此foo()执行错误。而function bar 是声明,它整体都被“提升”到了最前面,因此可以执行。

总结就是在函数首部定义所有需要的变量,这样就不会产生作用域混淆的问题,最好每个变量前都加var吧!

源地址请看这里

原文地址:https://www.cnblogs.com/simplevoid/p/2923585.html