变量的作用域和变量提升

京东面试题,面试官小姐姐给出了一道题:

var a = 100;
function test(){
    console.log(a);
    a = 10;
    console.log(a);
    console.log(this.a);
    var a;
}
test();

问我这三个会打印出来的值是什么?

好吧我这个还以为是要考我闭包的问题,后来一想是个变量提升的问题(好吧好吧,是小姐姐看我太尴尬了,就给我讲了一下)

回来研究一下这个变量的作用域和变量提升:

一、作用域:

一个变量的作用域(scope)是程序源代码中定义这个变量的区域。
全局变量拥有全局作用域,在javaScript代码中任何地方都有定义的。
然而在函数内声明的变量只是在函数内部有定义,他们是局部变量,作用域也只是在局部。

在函数体内,局部变量的优先级要高于全局变量。如果在函数体内重新声明一个与局部变量重名的变量,局部变量就会覆盖全局变量的值。
来看个例子:

var num="100";
function scope(){
    var num="10";
    function innerScope(){
        var num = "1";
        console.log(scope);//输出:1
    }
    innerScope();
    console.log(num);//输出:10
}
scope();
console.log(num);//输出:100

这个例子会打印三个数,分别是1,10,100;
局部变量的作用域仅仅在函数内部,出了函数体之后,局部变量就会被销毁。
在innerScope()函数中,虽然又声明了一个num,但是innerScope()中的num是局部变量,只是与全局变量的名字相同,并不是全局变量,所以,虽然在该函数中把num赋值为1,但这仅仅是一个与全局变量名称相同的一个变量而已,并没有改变全局变量的值。

再来看一个例子:

var num="100";
function scope(){
    var num="10";
    function innerScope(){
        num = "1";
        console.log(scope);//输出:1
    }
    innerScope();
    console.log(num);//输出:1
}
scope();
console.log(num);//输出:100

上面这部分代码中,在innerScope()函数中,我们并没有用var来声明num,所以,在这里的num的作用域就被提升了,即我们将scope中的num的值重置了,所以在输出的时候输出的结果为嵌套作用域内的局部变量。

二、变量提升

在Javascript中,函数及变量的声明都将被提升到函数的最顶部。
在js中,变量的声明会被解析器悄悄的提升到方法体的最顶部,但是需要注意的是,提升的仅仅是变量的声明,变量的赋值并不会被提升,我们需要注意的是,函数的声明与变量的声明是不一样的。函数的函数体也会被一起提升。
函数表达式和变量表达式只是其声明被提升,函数声明是函数的声明和实现都被提升。

所以上面那个题就很好理解了。
我们再来看一下这个题:

var num="100";
function scope(){
    var num="10";
    function innerScope(){
        var num = "1";
        console.log(scope);//输出:1
    }
    innerScope();
    console.log(num);//输出:10
}
scope();
console.log(num);//输出:100
  1. 因为变量提升,a提升到最前面,声明未赋值,所以第一个就会打印undefined;
  2. 第二个在a声明之后,而且a赋值为10,所以第二个打印出来10;
  3. 第三个,因为test()是在window下调用的;this指的是test()调用的作用域,所以第三个打印100;

看一个函数提升的例子:

<script language="javascript" type="text/javascript">    
    //在全局对象中声明两个全局函数,反模式  
    function foo()  
    {  
        alert("global foo");  
    }  

    function bar()  
    {  
        alert("global bar");  
    }  

    //定义全局变量  
    var v = "global var";  

    function hoistMe()  
    {  
        alert(typeof foo); //function  
        alert(typeof bar); //undefined  
        alert(v); //undefined  

        //为什么bar函数和变量v是未定义而不是全局变量中定义的相应的函数变量呢?  
         //因为函数里面定义了同名的函数和变量,无论在函数的任何位置定义这些函数和  
         //和变量,它们都将被提升到函数的最顶部。  

        foo(); //local foo  
        bar(); //报错,TypeError "bar is not a function"

        //函数声明,变量foo以及其实现被提升到hoistMe函数顶部  
        function foo()  
        {  
            alert("local foo");  
        }  

        //函数表达式,仅变量bar被提升到函数顶部,实现没有被提升  
        var bar = function()  
        {  
            alert("local bar");  
        };  


        //定义局部变量  
         var v = "local";  
    }  

    (function()  
    {  
        hoistMe();  

    })();  

   //函数表达式和变量表达式只是其声明被提升,函数声明是函数的声明和实现都被提升。  
    /**由于函数提升的效果,hoistMe方法相当于 
    function hoistMe() 
    { 
        //函数声明,变量foo以及其实现被提升到hoistMe函数顶部 
        function foo() 
        { 
            alert("local foo"); 
        } 

         //函数表达式,仅变量bar被提升到函数顶部,实现没有被提升(同变量提升) 
        var bar = undefined; 

        //变量声明被提升 
         var v = undefined; 

        alert(typeof foo); //function 
        alert(typeof bar); //undefined 
        alert(v); //undefined 

        foo(); //local foo 
        bar(); //报错,缺少对象 

        bar = function() 
        { 
            alert("local bar"); 
        }; 

       v = "local"; 

    } 
    */  
</script>  
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值