变量的作用域(scope)是程序源代码中定义这个变量的区域。简单的说,作用域就是变量与函数的可访问范围。全局变量拥有全局作用域,在JavaScript代码中的任何地方都能访问。局部变量是在函数体内声明而且只作用在函数体内部以及该函数体的子函数的变量。

变量作用域

  1. 如果一个变量在函数体内部申明,则该变量的作用域为整个函数体,在函数体外不可引用该变量
  2. 如果两个不同的函数各自申明了同一个变量,那么该变量只在各自的函数体内起作用
  3. 由于JavaScript的函数可以嵌套,此时,内部函数可以访问外部函数定义的变量,反过来则不行
  4. JavaScript的函数在查找变量时从自身函数定义开始,从“内”向“外”查找。如果内部函数定义了与外部函数重名的变量,则内部函数的变量将“屏蔽”外部函数的变量

全局作用域(Global Scope)

全部变量拥有全局作用域,在代码的任何地方都有定义,一般来说以下几种情形拥有全局作用域:

一、最外层函数和在最外层函数外面定义的变量拥有全局作用域

实例

<script>
        var scope="global";  //声明一个全局变量
        function checksope(){
            function showglobal(){
                alert(scope); //弹窗全局变量
            }
            showglobal();
        }
        checksope()   // global 内部函数可以访问全局变量
</script>

二、 所有末定义直接赋值的变量自动声明为拥有全局作用域

实例

<script>
        function checksope(){
            var scope = "local";
            scopeglobal = "global";
            alert(scope);
        }
        checksope(); // local
        alert(scopeglobal); // global不带var关键词声明的变量,直接升级为全局变量,同时也是全局变量的一个属性
        alert(scope); //脚本错误
</script>

//变量scopeglobal拥有全局作用域,而scope在函数外部无法访问到。

三、所有window对象的属性拥有全局作用域

一般情况下,window对象的内置属性都拥有全局作用域,例如window.name、window.location、window.top等等。

局部作用域(Local Scope)

局部作用域一般只在固定的代码片段内可访问到,最常见的例如函数内部,有人把这种作用域称为函数作用域

实例

<script>
        function  checksocpe(){
            var socpe="local";
            function inner(){
                alert(socpe);
            }
            inner();
        }
        alert(socpe);  //脚本错误
        inner();  //脚本错误 函数外部无法访问内部定义的函数
</script>

函数的提前声明

javascript的函数作用域是指在函数内声明的所有变量在函数体内始终是可见的,这意味着变量在声明之前甚至已经可用。JavaScript的这个特性被非正式地称为声明提前,即JavaScript函数里声明的所有变量(但不涉及赋值)都被”提前”至函数体的顶部。

实例

<script>
        var scope = "glocal";
        function f(){
           alert(scope);//输出"undefined",而不是"global"
           var scope = "local";//变量在这里赋初始值,但变量本身在函数体内任何地方均是有定义的
           alert(scope);//输出"local"
        }
        f();
    </script>

解析

也许您会误认为第一行会输出“global”,因为代码还没有执行到var语句声明局部变量的地方。其实不然,由于函数作用域的特性,局部变量在整个函数体始终是有定义的,也就是说,在函数体内局部变量覆盖了同名全局变量。尽管如此,只有在程序执行到var语句的时候,局部变量才会被真正赋值。因此,上述过程等价于:将函数内的变量声明“提前”至函数顶部,同时变量初始化留在原来的位置。

实例

<script type="text/javascript">
        var a = 10;
        function test(){
            a = 100; //当未定义的时候 “a”这个未声明的变量自动成为全局变量声明
            document.write(a + "<br/>");
            document.write(this.a + "<br/>");
            var a;
            document.write(a);
        }
        test();
</script>
//100 10 100

解析

Javascript在执行前会对整个脚本文件的声明部分做完整分析(包括局部变量),从而确定变量的作用域,所以在函数test执行前,由于第6行声明了局部变量a,所以函数内部的a都指向已经声明的局部变量,所以第4行输出100。第5行输出this.a,我们都知道,函数内部的this指针指向的是函数的调用者,在这里函数test被全局对象调用,所以this指针指向全局对象(这里即window),所以this.a = window.a,一开始声明了全局变量a=10,所以第5行输出结果为10。第7行输出结果为100,因为局部变量a在第3行已经被赋值了100,所以直接输出局部变量a的值。