JavaScript JS 作用域小问题

cbdfocus · 2015年09月02日 · 最后由 maomaoxgg 回复于 2015年09月03日 · 2749 次阅读

求教,请问最后 alert 为什么不是 2 ? var a = 3 ; 执行到这里的时候,都发生了什么!!!

<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <title>Basic1</title>
</head>
<body>
<button onclick="doit();">alert</button>


<script>

    var a = 10;
    function sth(){
        console.log(a);//undefine
        a=2;
        console.log(a);//2
        if(a >0){
            var a = 3;
            console.log(a);//3
        }
    }

    function doit(){
        sth();
        alert(a);//alert 10
    }

</script>

</body>
</html>
var chair = XiDaDa
。。。。
。。。。var chair = MaoZhuXi

然后 js 就崩了

2 楼 已删除

#2 楼 @billy 更新了一下,刚进入 sth 的时候 console.log(a);//undefine,无法自动向上获取变量?

@cbdfocus 刚才那个有问题。

#3 楼 @cbdfocus

var a = 10;
   var b = 10;
   function sth(){
       console.log(a);//undefine
       a=2;
       console.log(a);//2
       if(a >0){
            b = 3;
           console.log(a);//3
       }
   }

   function doit(){
       sth();
       alert(a+"+"+b);//2+3
   }

你再试下这个,再看看代码,你就明白了,你调的 a 是全局 a,想调 sth() 里的变量,把 alert 写到 sth() 里吧

#5 楼 @maomaoxgg


<script>

    var a = 10;
    var b = 10;
    function sth(){
        console.log(a);//10
        a=2;
        console.log(a);//2
        if(a >0){
            b = 3;
            console.log(a);//2
        }
    }

    function doit(){
        sth();
        alert(a+"+"+b);//2+3
    }

</script>

这样是我期待的结果了. 可是原帖中的现象要怎么解释呢?

@cbdfocus @maomaoxgg 根本原因在这里:var a = 3. Javascript 里面 var 定义不管是在什么地方,都自动等同于作用域顶部。所以你看似在代码中间定义了 var, 其实 function sth 一开始就知道 a 是一个本地变量了,a=2 其实改变的是本地变量,并非全局。

所以 coding 规范才推荐把 var 定义放在顶部,以免产生误解。

Variable declarations, wherever they occur, are processed before any code is executed. The scope of a variable declared with var is its current execution context, which is either the enclosing function or, for variables declared outside any function, global.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/var

#8 楼 @billy 对的,这就是我刚才写的 var 主席 = 习大大 再 var 个主席 = 胡大大 @cbdfocus

  1. 声明变量的作用域限制在其声明位置的上下文中,而非声明变量总是全局的。
  2. 声明变量在任何代码执行前创建,而非声明变量只有在执行赋值操作的时候才会被创建。
  3. 声明变量是它所在上下文环境的不可配置属性(non-configurable property),非声明变量是可配置的(例如非声明变量可以被删除)。

关于区别的第二条,是不是说,js 会先检查所有代码的 var 关键字,如果有声明就先占一个位置来明确作用域。这样理解对吗?@billy

var a = 'aa'
var a = 'aaa'

虽然这样写不好,但好像也没啥问题吧? @maomaoxgg

#10 楼 @cbdfocus 你所疑惑的这种现象叫做 Hoisting,可以看看这篇总结:http://segmentfault.com/a/1190000000348228

@cbdfocus 第二条你的理解是对的。

#10 楼 @cbdfocus 第一眼就感觉声明两次怪怪的,看了 @nightire 的链接,终于发现怪在哪儿了,帮你找问题的时候同时解了自己的惑,感觉空气好清新!

需要 登录 后方可回复, 如果你还没有账号请 注册新账号