第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()