Javascript中的this🏹

前面一直对js中的this概念含糊不清,进行彻底搞懂它!

今天在掘金上看到这么两道面试题,链接在此

自己先试着做了一下,第一道错的很惨,第二道就错了一个

难点分析

  • js中是以函数来划分作用域的,每个作用域都有一个this,指向它所属于的对象
  • 箭头函数的this指向最近外层的函数所属于的对象,如果没有的话则指向window对象

题目分析

第一道题目

第一组题目

1
2
3
4
5
6
7
8
9
10
11
var name = 'window'
var person1 = {
name: 'person1',
show1: function () {
console.log(this.name)
}
}
var person2 = { name: 'person2' }

person1.show1()
person1.show1.call(person2)

函数show1属于对象person1,所以其使用的thisperson1对象的this相同,所以输出为 person1

而使用call的话,这个show1的this就和传入call方法参数的对象相同了,所以输出为person2


第二组题目

1
2
3
4
5
6
7
8
9
var name = 'window'
var person1 = {
name: 'person1',
show2: () => console.log(this.name)}
}
var person2 = { name: 'person2' }

person1.show2()
person1.show2.call(person2)

箭头函数的作用域和最近的function相同,这里不存在,则直接指向 window 对象(注意,需在非严格模式下),所以输出为window

而即使使用了call方法,效果和perosn1相同,也无法将其和 person2绑定,所以输出依然为 window


第三组题目

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var name = 'window'

var person1 = {
name: 'person1',
show3: function () {
return function () {
console.log(this.name)
}
}
}
var person2 = { name: 'person2' }

person1.show3()()
person1.show3().call(person2)
person1.show3.call(person2)()

这里牵涉到闭包的问题,拿第一个person1.show3()()举例子,第一个括号表示返回内部的匿名函数至对象person1外部,第二个括号表示调用匿名函数,执行其内部的逻辑。

对于第一个,最里面的闭包函数最后被返回到最外层,也就是全局里,所以里面的this指向 window对象

而第二个,最后是将匿名函数的 thisperson2 绑定了,所有输出的是 person2name 属性的值,也就是 person2

最后一个,它是在第一阶段绑定的,这没用,因为那时内部的匿名函数还未执行,所有依然输出 window


第四组题目

1
2
3
4
5
6
7
8
9
10
11
var person1 = {
name: 'person1',
show4: function () {
return () => console.log(this.name)
}
}
var person2 = { name: 'person2' }

person1.show4()()
person1.show4().call(person2)
person1.show4.call(person2)()

最里面的匿名函数适合最近外层的函数有相同的this,即这个匿名函数;也就说最后三行的执行,决定输出结果的是第一个函数括号,也就是那个匿名函数的this到底是指向 person1还是 person2,和第二个括号的执行,也就是匿名函数本身的执行无关;这样子一下子都出来了,输出依次是:person1person1person2


第二道题目

这个题目就不详细分析了,就分析最后一组,也是我错的那一组

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var name = 'window'

function Person (name) {
this.name = name;
this.show4 = function () {
return () => console.log(this.name)
}
}

var personA = new Person('personA')
var personB = new Person('personB')

personA.show4()()
personA.show4().call(personB)
personA.show4.call(personB)()

这个和第一道题目的第四组类似,遇到箭头函数首先找其最近外层的函数,发现是 this.show4 = function(){....},也就是说这个箭头函数的thisPerson实例化的对象的this相同,所有这决定这组题目输出结果的就是第一个括号的那个函数,也就是 show4 = function(){....}this 到底是和那个对象绑定的,第一二个是和personA,而最后一个使用 call 方法和 person2 绑定了;所以输出依次为:personApersonApersonB