深入理解JavaScript的变量作用域(转载Rain Man之作)

在学习JavaScript的变量作用域之前,我们应当明确几点:

  • JavaScript的变量作用域是基于其特有的作用域链的。
  • JavaScript没有块级作用域。
  • 函数中声明的变量在整个函数中都有定义。

1、JavaScript的作用域链

首先看下下面这段代码:

<script type="text/javascript">
    var rain = 1;
    function rainman(){
        var man = 2;
        function inner(){
            var innerVar = 4;
            alert(rain);
        }
        inner();    //调用inner函数
    }
    rainman();    //调用rainman函数
</script>

观察alert(rain);这句代码。JavaScript首先在inner函数中查找是否定义了变量rain,如果定义了则使用inner函数中的rain变量;如果inner函数中没有定义rain变量,JavaScript则会继续在rainman函数中查找是否定义了rain变量,在这段代码中rainman函数体内没有定义rain变量,则JavaScript引擎会继续向上(全局对象)查找是否定义了rain;在全局对象中我们定义了rain = 1,因此最终结果会弹出‘1‘。

作用域链:JavaScript需要查询一个变量x时,首先会查找作用域链的第一个对象,如果以第一个对象没有定义x变量,JavaScript会继续查找有没有定义x变量,如果第二个对象没有定义则会继续查找,以此类推。

上面的代码涉及到了三个作用域链对象,依次是:inner、rainman、window。

2、函数体内部,局部变量的优先级比同名的全局变量高。

<script type="text/javascript">
    var rain = 1;    //定义全局变量 rain
    function check(){
        var rain = 100;    //定义局部变量rain
        alert( rain );       //这里会弹出 100
    }
    check();
    alert( rain );    //这里会弹出1
</script>

3、JavaScript没有块级作用域。

这一点也是JavaScript相比其它语言较灵活的部分。

仔细观察下面的代码,你会发现变量i、j、k作用域是相同的,他们在整个rain函数体内都是全局的。

<script type="text/javascript">
    function rainman(){
        // rainman函数体内存在三个局部变量 i j k
        var i = 0;
        if ( 1 ) {
            var j = 0;
            for(var k = 0; k < 3; k++) {
                alert( k );    //分别弹出 0 1 2
            }
            alert( k );        //弹出3
        }
        alert( j );            //弹出0
    }
</script>

4、函数中声明的变量在整个函数中都有定义。

首先观察这段代码:

<script type="text/javascript">
    function rain(){
        var x = 1;
        function man(){
            x = 100;
        }
        man();        //调用man
        alert( x );    //这里会弹出 100
    }
    rain();    //调用rain
</script>

上面得代码说明了,变量x在整个rain函数体内都可以使用,并可以重新赋值。由于这条规则,会产生“匪夷所思”的结果,观察下面的代码。

<script type="text/javascript">
    var x = 1;
    function rain(){
        alert( x );        //弹出 ‘undefined‘,而不是1
        var x = ‘rain-man‘;
        alert( x );        //弹出 ‘rain-man‘
    }
    rain();
</script>

是由于在函数rain内局部变量x在整个函数体内都有定义( var x= ‘rain-man‘,进行了声明),所以在整个rain函数体内隐藏了同名的全局变量x。这里之所以会弹出‘undefined‘是因为,第一个执行alert(x)时,局部变量x仍未被初始化。

所以上面的rain函数等同于下面的函数:

function rain(){
    var x;
    alert( x );
    x = ‘rain-man‘;
    alert( x );
}

5、未使用var关键字定义的变量都是全局变量。

<script type="text/javascript">
    function rain(){
        x = 100;    //声明了全局变量x并进行赋值
    }
    rain();
    alert( x );    //会弹出100
</script>

这也是JavaScript新手常见的错误,无意之中留下的许多全局变量。

6、全局变量都是window对象的属性

<script type="text/javascript">
    var x = 100 ;
    alert( window.x );//弹出100
    alert(x);
</script>

等同于下面的代码

<script type="text/javascript">
    window.x = 100;
    alert( window.x );
    alert(x)
</script>
时间: 2024-10-10 22:00:06

深入理解JavaScript的变量作用域(转载Rain Man之作)的相关文章

深入理解JavaScript的变量作用域

在学习JavaScript的变量作用域之前,我们应当明确几点: JavaScript的变量作用域是基于其特有的作用域链的. JavaScript没有块级作用域. 函数中声明的变量在整个函数中都有定义. 1.JavaScript的作用域链 首先看下下面这段代码: 1 <script type="text/javascript"> 2 var rain = 1; 3 function rainman(){ 4 var man = 2; 5 function inner(){ 6

[转]深入理解JavaScript的变量作用域

1.JavaScript的作用域链 2.函数体内部,局部变量的优先级比同名的全局变量高. 3.JavaScript没有块级作用域. 4.函数中声明的变量在整个函数中都有定义. 5.未使用var关键字定义的变量都是全局变量. 6.全局变量都是window对象的属性 在学习JavaScript的变量作用域之前,我们应当明确几点: JavaScript的变量作用域是基于其特有的作用域链的. JavaScript没有块级作用域. 函数中声明的变量在整个函数中都有定义. 1.JavaScript的作用域链

JavaScript的变量作用域深入理解

在学习JavaScript的变量作用域之前,我们应当明确几点: a.JavaScript的变量作用域是基于其特有的作用域链的. b.JavaScript没有块级作用域. c.函数中声明的变量在整个函数中都有定义. <script> var x = 1; function outer() { var y = 2; function inner() { var z = 4; alert(x); } inner(); } outer(); </script> alert(x)这句代码,J

理解javascript原型和作用域系列(1)——一切都是对象

“一切都是对象”这句话的重点在于如何去理解“对象”这个概念. ——当然,也不是所有的都是对象,值类型就不是对象. 首先咱们还是先看看javascript中一个常用的函数——typeof().typeof应该算是咱们的老朋友,还有谁没用过它? typeof函数输出的一共有几种类型,在此列出: function show(x) { console.log(typeof(x)); // undefined console.log(typeof(10)); // number console.log(t

理解javascript原型和作用域系列(12)——简介【作用域】

前几节的文章请查阅<理解javascript原型和作用域系列> 提到作用域,有一句话大家(有js开发经验者)可能比较熟悉:"javascript没有块级作用域".所谓"块",就是大括号"{}"中间的语句.例如if语句: 再比如for语句: 所以,我们在编写代码的时候,不要在"块"里面声明变量,要在代码的一开始就声明好了.以避免发生歧义.如: 其实,你光知道"javascript没有块级作用域"是

理解javascript原型和作用域系列(9)——简述【执行上下文】下

继续上一篇文章(http://www.cnblogs.com/wangfupeng1988/p/3986420.html)的内容. 上一篇我们讲到在全局环境下的代码段中,执行上下文环境中有如何数据: 变量.函数表达式——变量声明,默认赋值为undefined: this——赋值: 函数声明——赋值: 如果在函数中,除了以上数据之外,还会有其他数据.先看以下代码: 以上代码展示了在函数体的语句执行之前,arguments变量和函数的参数都已经被赋值.从这里可以看出,函数每被调用一次,都会产生一个新

理解javascript原型和作用域系列(8)——简述【执行上下文】

什么是“执行上下文”(也叫做“执行上下文环境”)?暂且不下定义,先看一段代码: 第一句报错,a未定义,很正常.第二句.第三句输出都是undefined,说明浏览器在执行console.log(a)时,已经知道了a是undefined,但却不知道a是10(第三句中). 在一段js代码拿过来真正一句一句运行之前,浏览器已经做了一些“准备工作”,其中就包括对变量的声明,而不是赋值.变量赋值是在赋值语句执行的时候进行的.可用下图模拟: 这是第一种情况. 下面还有.先来个简单的. 有js开发经验的朋友应该

理解javascript原型和作用域系列(5)——instanceof

又介绍一个老朋友——instanceof. 对于值类型,你可以通过typeof判断,string/number/boolean都很清楚,但是typeof在判断到引用类型的时候,返回值只有object/function,你不知道它到底是一个object对象,还是数组,还是new Number等等. 这个时候就需要用到instanceof.例如: 上图中,f1这个对象是被Foo创建,但是“f1 instanceof Object”为什么是true呢? 至于为什么过会儿再说,先把instanceof判

理解javascript原型和作用域系列(3)——prototype原型

既typeof之后的另一位老朋友! prototype也是我们的老朋友,即使不了解的人,也应该都听过它的大名.如果它还是您的新朋友,我估计您也是javascript的新朋友. 在咱们的第一节(理解javascript原型和作用域系列(1)——一切都是对象)中说道,函数也是一种对象.他也是属性的集合,你也可以对函数进行自定义属性. 不用等咱们去试验,javascript自己就先做了表率,人家就默认的给函数一个属性——prototype.对,每个函数都有一个属性叫做prototype. 这个prot