简述this(2):常见面试题分析

第1题

var name = "222"

var a = {
    name: "111",
    say: function () {
        console.log(this.name)
    }
}

a.say()

say函数在执行时是被对象a所调用的,所以this指向对象a
因此最后输出 111

第2题

var name = "222"

var a = {
    name: "111",
    say: function () {
        console.log(this.name)
    }
}

var fun = a.say
fun()

fun拿到了a.say这个函数的引用,当我们在全局环境中执行fun()时(并没有被谁调用)
就相当于在全局环境执行: function() { console.log(this.name) }
所以执行时this指向window,因此最终输出 222

第3题

var name = "222"

var a = {
    name: "111",
    say: function () {
        console.log(this.name)
    }
}

var b = {
    name: "333",
    say: function(fun){
        fun()
    }
}

b.say(a.say)

把a.say当作参数传入b.say当中,相当于如下写法:

var name = "222"
var b = {
    name: "333",
    say: function(){
        
        function s(){
            console.log(this.name)
        }
        s()
    }
}

需要注意的是,在b.say函数中,this确实指向的是对象b
但是函数s在执行的时候并没有被谁调用(前面没有任何修饰符)
因此s在执行的时候 内部的this指向window,最终输出 222

第4题

var name = "222"

var a = {
    name: "111",
    say: function () {
        console.log(this.name)
    }
}

var b = {
    name: "333",
    say: function(fun){
        fun.call(b)
    }
}

b.say(a.say)

使用call来执行函数fun,导致fun内部的this指向了b
因此,最终输出333

第5题

var age = 26
var userInfo = {
  age:13,
  updateInfo:function(){
  
      setTimeout(function() {
        this.age = 39
        console.log(userInfo.age)
      },100)
      
  }
}

userInfo.updateInfo()

我们的初衷是:在upadateInfo执行的100ms之后,修改userInfo.age的值
然而最终输出的仍然是13(也就是说,userInfo.age并没有被修改)

那么,this.age = 39到底修改的是谁的age呢?
答案是window
因为setTimeout是异步任务,它会等到同步任务结束后 再在全局环境中执行
这个时候的this,无疑指向了window

那么应该如何修改呢?
方法一:利用let创建块级作用域

var age = 26
var userInfo = {
  age:13,
  updateInfo:function(){
      let self = this
      setTimeout(function() {
        self.age = 39
        console.log(userInfo.age)
      },100)
      
  }
}

userInfo.updateInfo()

我们用self来缓存指向对象userInfo的this
当我们执行userInfo.updateInfo( )的第0ms时,setTimeout的回调函数被声明
此时它的作用域链为:updateInfo对应的活动对象{self} --> 全局对象{age=26, userInfo}
100ms之后,回调函数被执行,此时它的作用域链为:
自身对应的活动对象{ } --> updateInfo对应的活动对象{self} --> 全局对象{age=26, userInfo}

这个写法就不需要考虑this的绑定规则了,因为没有出现过this.xxx

方法二:箭头函数

var age = 26
let userInfo = {
  age:13,
  updateInfo:function(){
  
      setTimeout(() => {
        this.age = 39
        console.log(userInfo.age)
      },100)
    
    
  }
}
userInfo.updateInfo()
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容