一道js面试题,觉得和变量提升有关

(function(){
    a = 5;
    alert(window.a);
    var a = 10;
    alert(a);
})();

这个先打印出 undefined 然后是10,为什么呀?

阅读 14.1k
12 个回答

第一个 a=5 没用var, 它并没有创建变量a, 而是向上级作用域找变量a, 自然是找不到, 所以会创建a, 但创建的a是本域的, 不是window域(顶级域)的, 所以window.a还是undefined .

(function(){
    a = 5;
    alert(a);           //==> 5
    alert(window.a);    //==> undefined
    var a = 10;
    alert(a);           //==> 10
})();

首先明确2点:
1、js中没有带var关键字的变量都是隐式全局变量
2、js中存在变量提升

上述的代码等效于:

var a=undefined;  
(function(){
    var a;    //局部变量a,默认值是undefined
    a = 5;    //因和局部变量名相同,因此全局变量a被覆盖,此处变成了给局部变量a赋值
    //alert(a);  弹出5
    //a只是变量,而不是属性 alert(a in window)返回false  ,参见http://segmentfault.com/q/1010000002883076 的第一个回答
    alert(window.a);  
    a = 10;
    alert(a);
})();
新手上路,请多包涵

这题目有点神奇 不只是变量提升 是变量提升的应用了。。正解是 var a = 10 在预编译的时候会在函数里进行变量提升,这个大家都回答到了,然后 变量提升相当于进行了var a 操作,然后a =10 这条代码解释执行的时候。。变成了赋值操作,不再进行隐式生命全局变量的操作,导致window.a为undefined,出这道题的人真的机智!!!!!!!

因为a在下面被声明过了,所以预解释为undefined,window.a之前a没有赋值,所以为undefined,下面的a声明并且赋值所以为10

@不写代码的码农 首先他的回答已经很好了,希望你明白,作为初学者,说说我个人的比较通俗的理解,望指正。

javascript    (function(){
    a = 5;            
    alert(window.a);  
    var a = 10;    //由于声明提前,var a是这个匿名函数中的局部变量,js引擎会在执行前
                  // 最先编译。
                   //所以,第一行的a=5其实不是创建了全局变量,而是对编译期间的局部变量
                   // a赋值5.
                   //但是,为何alert(window.a)会是undefined,是因为他指定了要输出的
                   //是window.a
                   //这是要输出window的属性a,没有这个a,因此会是输出undefined(此
                   //处,我也有疑问,
                   //为何不会出现referenceError),之后再赋值10,那么输出的就是10了
    alert(a);
})();

其中,我不明白的地方提出来了,可能有误,希望指正。-----初学

(function(){
    a = 5; 
    alert(window.a);
    var a = 10;
    alert(a);
})();

你可以把那个未声明的变量a当作不存在 这样就会好一些

(function(){

a = 5; //没有用var声明的变量,它才会在全局对象(即当前作用域链的最顶层对象,如window对象创建一个变量--全局变量),所以window.a应该相当于var a;所以window.a是undefined。
alert(window.a);
var a = 10;
alert(a);

})();

需要知道js的预编译模式的函数声明会先找到变量赋值语句,并将其置于函数顶,赋值为undefined.
了解完这个自己就能读懂了, 虽然a=5看上去是声明了一个全局变量,但是后面有一个var a = 10所以导致变量提升,所以代码预编译完成之后会变成下面这个样子:

(function(){
        var a;    //    undefined
    a = 5;    //    5
    alert(window.a);    //此时的a的scope是该函数
    var a = 10;    //10
    alert(a);    //10
})();

(function(){

a = 5;
alert(window.a);
var a = 10;
alert(a);

})();
//预编译之后
(function(){

var a; //变量提升了,为局部变量,作用域是function里
a = 5; // 被重新赋值为5
alert(window.a); //返回undefined,window是js存在的一个对象,在查找一个属性时,从本身,沿着原    
                 //型链开始查找,直到最顶端null,还找不到,则返回undefined
a = 10; // 重新赋值为10
alert(a); // 10

})();

另外,提供一个不错的变量提升资料 :https://www.cnblogs.com/liuhe...

这段代码是一个自执行匿名函数,当函数执行的时候,会创建自己的执行上下文,然后创建AO对象,然后扫描该执行上下文中的var变量声明,扫描结束时得到AO={ a: undefined },然后执行阶段,开始逐行执行代码,执行到a=5时,首先会到当前AO中找a,找到后修改a=5;此时AO = {a:5},执行到alert(window.a)时,这里比较特殊,在全局执行上下文中VO中有一个属性window指向VO自身,而全局VO中存放的都是全局执行上下文的声明的变量和函数,而这段代码中并没有任何全局声明,因此window.a是undefined,执行到a = 10时,修改a=10,此时AO={a:10},所以得到alert(a);//10

以上是关于JS底层执行原理的粗略过程,详细过程自行查阅

可否这么理解


    // 预编译顺序
    // 执行顺序
    (function(){
      // 变量提升
      // 声明函数作用域的变量a为局部变量
      var a;
      // window 这里是个对象,相当于对象根据原型链查找属性
      // 相当于声明全局作用域的变量a为全局变量
      window.a;
      // 给函数作用域的变量a赋值
      a = 5;
      // 弹出全局作用域的变量a
      alert(window.a);
      // 给函数作用域的变量a赋值覆盖
      a = 10;
      // 弹出函数作用域的变量a
      alert(a);
      
    })()
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏