JavaScript关于this的一道小题

var a = 10;
var obj1 = {
    a: 20,
    fn: (function() {
        this.a *= 2;
        a = 5;
        var a = 6;
        return function() {
            this.a *= a;
            console.log(a)
        }
    })()
}
var obj2 = {
    a: 30
}
var fn = obj1.fn;
fn();  //6???
obj1.fn();  //6???
obj1.fn.call(obj2);  //6???

如上所示,函数运行之后,结果分别是6,6,6,但是我想来想去都不明白为什么是6....,就算var a = 6之后a等于6了,那为什么this.a *= a 之后a还是等于6呢?求大神指点一二。

阅读 1.9k
1 个回答
var a = 10 // -> window.a 这个 a 是挂载在 window 下的
var obj1 = {
  a: 20,
  fn: (function() {
    // 立即执行函数 AO
    // 因为函数体内有 var 变量声明,在预编译时 AO 下会挂载一个 a
    // AO.a
    this.a *= 2
    // 立即执行函数的 this 指向 window
    // 既 window.a *= 2 -> window.a = 20

    a = 5
    // AO.a = 5

    var a = 6
    // AO.a = 6

    return function() {
      // AO1

      this.a *= a
      console.log(a)
    }
  })(),
}
var obj2 = {
  a: 30,
}
var fn = obj1.fn
// fn 既 AO 返回的函数 AO1

fn() //6???
// 当执行 fn 时,时在全局直接调用的的,相当于执行 window.fn
// this.a *= a -> window.a = 400
// console.log(a) -> 先找 AO1.a 是否存在(没有) -> 查找 AO.a 是否存在(存在) -> 使用 AO.a -> 输出 6

obj1.fn() //6???
// 因为是 obj1 调用的 fn ,所以 fn 内部的 this -> obj1
// this.a *= 2 -> obj1.a *= 2 -> obj1.a = 40
// 查找原理同上,输出 6

obj1.fn.call(obj2) //6???
// 使用 call 改变 this 指向,所以 fn 内部的 this -> obj2
// this.a *= 2 -> obj2.a *= 2 -> obj2.a = 60
// 查找原理同上,输出 6

上面注释只是说了是什么,而没说为什么.

如果你想要完全理解为什么的话,可以自行搜索关键词预编译,作用域,作用域链,变量提升等关键词.

也可以看看下面的参考链接.

或者可以看最后的视频,我第一次了解到预编译就是在那个视频里面看到的.我给的链接的小节是讲预编译,之前的章节有讲作用域,如果基础比较差就从头看起吧.
之所以推荐,首先肯定是讲的好,值得推荐.当然最重要的是免费的.ヾ(≧▽≦*)o

参考

文章

视频

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