4 个回答
1  var foo = 1;
2  function main(){
3      alert(foo);
4      var foo = 2;
5      alert(this.foo);
6      this.foo = 3;
7  }
8  main(); // undefined  1 
9  alert(foo);  // 3
10 new main(); // undefined undefined

浏览器执行Js程序的时候,分两步:

(1)预解析(变量声明提升)
    在代码解读之前发生,相当于一个"仓库",放一些东西,比如var、function、参数等。
    预解析时变量都是未定义的,函数则是整个函数块。
    预解析时遇到重名的,会覆盖。变量与函数,留函数;函数与函数,留后面解析的。
    当代码在一个环境中执行时,会创建变量对象的一个作用域链。是域就要预解析。

(2)执行代码
    代码自上而下,从左往右的执行,读到表达式时,预解析仓库中的东西发生改变。

我们来分析题目
先预解析,预解析仓库里有:

foo = undefined;
function main(){}

执行代码:

第1行: 赋值 foo = 1;
2-7行: 函数声明,不影响预解析仓库;
第8行: 执行 main(); main函数内部预解析,函数预解析仓库里有:
            局部 foo = undefined;
        然后执行第3行,由于此时函数局部预解析foo还未定义,所以alert出undefined;
        继续执行第4行,赋值2给局部foo变量,*注意*函数外部foo此时还是1;
        继续执行第5行,此时main函数相当于是window在调用,所以this指向window;window层变量就相当于window的属性,最外层foo为1,所以弹出1;
        继续执行第6行,将window下的foo属性值改为3,此时最外层foo由1变为3;
        *注意我添的第9行*,可以证实外部foo变为3了;
第10行: 执行new main();
            new操作符调用构造函数创建对象的步骤?
              (1)创建一个新对象;
              (2)将构造函数的作用域赋给新对象(因此this就指向了这个新对象)
              (3)执行构造函数中的代码(为这个新对象添加属性)
              (4)返回新对象
            new构造新对象时要执行构造函数,所以main此时也要执行,也要预解析,同上第8行分析,
            不同点是此时this指向的是new出来的新实例对象,新实例对象上没foo属性,foo原型链上也没有;
            所以两次都alert出undefined;

综上选A

main函数中第一个alert考的是scope chain。他会现在在main函数中查找是否有foo变量,没有才回去上层的scope中查找。因为main函数中有声明foo变量,但是alert在他赋值之前,所以返回的是undefined。
第二个alert考的是this指向的问题。

  • 当函数作为一个对象属性被调用时,this指向的就是他的调用者,即那个对象;

  • 当函数直接被调用时,他的调用者其实就是window对象;

  • 当函数作为构造函数被执行时,他的this指向的是构造函数实例化出来的对象;

  • 我们还可以使用call/apply来改变默认的this指向。

主要在于两个问题: this 的值和变量声明提升。

THIS
main() 这样的话,this 是 window
new main() this 是以这个函数为原型新创建的对象,所以在给 this.foo 赋值的前肯定是 undefined
http://zonxin.github.io/post/2015/11/javascript-this

变量声明提升:
所有以 var 这样声明的局部变量都会本人为是定义在该函数的一最开始,而var a=2。而其赋值还是在原来的位置。因此, 在函数里 foo 是 undefined。
其实是js 在执行函数的时候先把函数扫描一遍(ES5.1),定义所有的变量和函数,并赋予初值。然后除去变量和函数声明,执行这个函数。
http://zonxin.github.io/post/2015/10/javascript-hoisting

第一个alert考的是变量声明提升,实际上执行代码的顺序是:

var foo;
alert(foo);
foo = 2;

所以第一个alert始终返回undefined

第二个alert考的是this
第一次是直接调用,this指向全局作用域,所以结果是1
第二次是作为构造函数调用,this指向构造的实例对象,在为构造函数初始化属性之前返回this.fooundefined

this的值与它在什么地方无关,在于它所在函数被何种方式调用。深入javascript——无处不在的this

推荐问题
宣传栏