javascript中关于函数中赋值的疑问

<script type="text/javascript">
        var str1="b";
        function test(){
            alert(str1); 
            var str1 = "c";
        }
        test();
</script>

对于上面这段代码,为什么单单var str1 = "c"就会使得str1的值为undefined呢?
主要的疑惑和请教:

  • alert(str1)语句位于var str1 = "c"之前,为什么会受它的影响呢?

  • 此过程中全局变量str1发生了什么变化?

阅读 8.1k
6 个回答

参考这里变量声明提升部分

这是JavaScript的变量声明提升效果 - hoisting
以上代码在运行时会变为这样

<script type="text/javascript">
        var str1="b";
        function test(){
            var str1;
            alert(str1); 
            str1 = "c";
        }
        test();
</script>

js只有函数作用域,所以alter(str1)时现在本函数作用域查找变量,此时只是进行了var str1 那么返回的就是undefined,如果本函数作用域没有此变量的声明,才会依据作用域链向外寻找。

前面的回答都不错
补充局部变量与全局变量的关系。
设置一个全局变量,需在任何函数之外用var声明,对所有函数有效。
设置一个局部变量,就在需要的地方var声明。

var a=1;
function f(){
    var a=2;
    alert(a);
}
alert(a);

上面的代码中,全局变量a的值为1。局部变量a为2。
在一个function中,如果全局变量与局部变量重名,局部变量优先级高。所以在f()的alert中,a的值为2。
然而局部变量顾名思义,就是只在局部范围内生效的函数。所以a=2只在f()中生效,所以第二个alert的值为1。
再结合上面的回答,就解决了。
另外,更改一个函数的值的方法是直接赋值,不加var

题主的第一个疑问,是关于变量提升的问题。

原代码

var str1="b";
        function test(){
            alert(str1); 
            var str1 = "c";
        }
        test();

等同于

function test(){
            var str1;
            alert(str1); 
            str1 = "c";
        }
var str1;
str1="b";
test();

简单点说,JavaScript中只有用var声明的变量(ES6里新出的声明变量的let和声明常量的const都没这个讲究)和函数声明(注意!是函数声明!不包括var f = function(){}等等这样的函数表达式!)才有变量提升现象。

其中,函数声明优先级高于用 var 声明的变量,JavaScript引擎会先解析。

对函数声明来说,变量提升会带着函数体一起放到区域执行环境的前端;对变量声明来说,只提升变量,不提升声明。(比如你代码中的str1声明被提前,赋值还保留在原来的那一行。)

题主的第二个问题,是关于执行环境和作用域链的问题。

此过程中全局变量str1没变化,因为不关它事。

作用域链其实是个保证访问顺序的东西。这顺序是由里往外,由下至上的。作用域链的前端始终是当前执行代码所在环境的变量对象。在当前环境中拿到了它想要的值(别管是什么值,哪怕是个只声明未赋值的undefined),就不会沿着作用域链继续向上查找了。

请注意js的变量声明有hoisting 变量提升...函数内执行的相当于

var str1;
alert(str1);
str1 = 'a';

由于变量提升的原因,实际执行的代码相当于是

<script type="text/javascript">
        var str1="b";
        function test(){
            var str1;
            alert(str1); 
            str1 = "c";
        }
        test();
</script>

函数内部有定义变量名为str1的变量,这个时候他回覆盖函数外的同名变量,而且根据变量提升原理,在执行执行alert(str1)之前,str1只是在函数内部进行了定义,但并没有实际的赋值。所以输出也就是undifined了

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题