我相信很多C系语言的学习者和使用者,在学习和使用javascript的时候,总会被其变量作用域迷惑一下, 我觉得这是很正常的,因为他确实跟c和java等不太一样

变量作用域的概念 
在程序设计中,变量的可访问性和生命周期都是有一定范围的,而这一定范围就是变量的作用域,也就是说,作用域控制着变量的可访问性和生命周期

JavaScript中没有块级作用域,只有函数作用域

Java:

class Person{
     public void run(){

          for(int i=0; i<5; i++){
               String str = "the i is " +i;  //这里str只能在for循环块里面有效
          }
          System.out.println(str); // 这里是无法访问str,编译无法通过
     }     
}

JavaScript:

function run(){
     for(var i=0; i<5; i++){
              var str = "the i is " +i;  //这里str将在整个函数run中里面有效
     }
     console.log(str); // 这里将会输出“the i is 4”
}

在现在很多高级语言中, 总是被建议尽量在使用的地方并且在尽可能迟的时候声明变量,但是在js中, 通过上面的分析,你会发现最好在函数的开始处声明变量,因为你无论在函数哪个地方声明变量,都是在function中有效,所以何不在函数开始处定义,提供程序的可读性呢?!这在js中会是一个比较好的编程习惯

JavaScript中没有声明变量类型的变量是全局变量

function run(){
     for(var i=0; i<5; i++){
          str = "the i is " +i;  //code 如此编写,合乎语法,但是全局变量
     }
     console.log(str); // 这里将会输出“the i is 4”
}
function go(){
     console.log(str); //这里将会输出“the i is 4”    
}

希望闭包不会迷惑你(闭包中,以上两条原则都满足) 
JavaScript:

var myObject = function (  ) {
    var value1 = 0;
    value2 = 1;
    return {
        increment: function (inc) {

            value += typeof inc === 'number' ? inc : 1;
        },
        getValue: function (  ) {
            return value;
        }
    }
}();

function test(){
     console.log(value1); // 这里将会报错:“ReferenceError:value1 is not defined”
     console.log(value2); // 这里输出“1”
}

用原理性的言论理解上面两条原则 
JavaScript中有两个比较重要的概念:执行环境(上下文)和作用域链; 
执行环境:当前程序运行的环境,当创建function时,就会创建一个执行环境,即一个function有着自己的上下文; 
作用域链:正是因为javascript中有闭包(函数中套函数),才会有作用域链的概念,如上面的那个闭包程序

JavaScript程序运行时,即在程序的执行环境中,程序总是按到作用域链向上搜索变量;

var value3 = 0;

var myObject = function (  ) {
    var value1 = 0;
    value2 = 1;
    return {
        increment: function (inc) {

            value += typeof inc === 'number' ? inc : 1;
        },
        getValue: function (  ) {
            return value;
        }
    }
}();

上面的执行环境、作用域链如下图:

参考: 
《JavaScript: The Good Parts》(中文翻译为《javascript语言精粹》) 
《Javascript高级程序设计》

16 5

共收到5条回复

聂银银 859天前 #1楼

自己顶!!!!!!!!!!!!!

0 评论

极客学院-shao 859天前 #2楼

#1楼 @聂银银 棒棒哒,帮你顶

0 评论

eclipse_xys 859天前 #3楼

不错 很赞 把技术细节写清楚了!

0 评论

MiYogurt 859天前 #4楼

ES5中 with,TryCatch的Catch也是块级作用域。ES6里面加入了块级作用域。

0 评论

烟火颜色 706天前 #5楼

学习了,非常感谢~~~

0 评论

加入小组与大家一起讨论吧