JavaScript中的this
一直是面试中的热点问题,同时也是JavaScript中的一个难点问题,在JavaScript中this
的指向十分灵活,使用场景也很多,所以对于this的熟练掌握是我们前端工程师的一个基本技能之一。今天我们来通过7个实例来讲解this
在一些场景中的指向问题,大家也可以先看代码,自己先思考答案,再看自己的答案是否是正确的。
有一种民间流传的说法:“谁调用它,this就指向谁”,这句话其实并不全面,我们还要根据实际情况进行逐个分析。
我想一篇文章里放太多的题目实例也不好,像做考试题似的,所以我会分多篇文章去发布this指向的内容。
全局环境中的this
基础版本
function fn1 () {
console.log(this)
}
function fn2 () {
'use strict'
console.log(this)
}
fn1() //?
fn2() //?
这种情况还算简单,因为函数在全局环境中被调用,在非严格模式下this指向window,在严格模式下指向undefined。所以这道题的答案是window
和undefined
。
升级版本
const obj = {
abc: 10,
fn: function() {
console.log(this)
console.log(this.abc)
}
}
let fn1 = obj.fn
fn1() // ?
这里的this仍然指向window,因为fn函数虽然是作为对象的一个方法,但是在赋值给fn1之后,fn1仍然是在全局环境中执行的,所以这道题的答案是window
和undefined
。
如果是这样呢?
const obj = {
a: 10,
fn: function() {
console.log(this)
console.log(this.a)
}
}
obj.fn() // ?
这就是我们常规的使用方式了,this指向的是调用它的对象,也就是obj对象,所以会输出下面的内容
{a: 10, fn: ƒ}
10
这里要记住,如果函数式被上一级对象调用那么this就指向上一级这个对象,否则就指向全局环境。
对象调用中的this
基础版本
根据上面所讲,再遇到这样的题目时,就要融会贯通。
const user = {
name: 'shuai',
fn: function() {
return this
}
}
console.log(user.fn() === user) // ?
函数被user对象所调用,所以this指向为user对象,所以这道题答案为true
。
复杂调用版本
const user = {
name: 'shuai',
friend: {
name: 'guan',
fn: function() {
return this.name
}
}
}
console.log(user.friend.fn()) // ?
摸清套路之后,再复杂的调用关系也不怕,根据上面所说“函数式被上一级对象调用那么this就指向上一级这个对象”,所以这道题的答案是输出guan
。
更高阶版本
const u1 = {
name: 'u1',
fn: function() {
return this.name
}
}
const u2 = {
name: 'u2',
fn: function() {
return u1.fn()
}
}
const u3 = {
name: 'u3',
fn: function() {
let fn = u1.fn
return fn()
}
}
console.log(u1.fn()) // ?
console.log(u2.fn()) // ?
console.log(u3.fn()) // ?
-
首先来说第一个
u1.fn()
,这个比较简单,和上面一样,答案为输出u1
。 -
第二个相对来讲也还可以,因为
u1.fn()
返回的就是u1
,所以u2.fn()
返回的也就是u1
。 -
第三个
u3.fn()
相对就很难了,因为它把u1.fn
赋值给了fn
,然后直接调用的fn
函数。所以这里的this指向是window,所以答案是输出undefined
。
所以这个公式一定要背下来,不然就会发懵。
这里要记住,如果函数式被上一级对象调用那么this就指向上一级这个对象,否则就指向全局环境。
变种版本
const u1 = {
name: 'u1',
fn: function() {
return this.name
}
}
const u2 = {
name: 'u2',
fn: u1.fn
}
console.log(u2.fn()) // ?
这道题,首先是把u1.fn
赋值给u2.fn
,然后调用了u2.fn()
,因为调用fn
的是u2对象,所以this指向的就是u2对象,所以输出的将是u2
。
今天规律总结
- 在函数中,严格模式this会被绑定到undefined上,非严格模式会被绑定到window全局对象
- 通过上下文对象调用函数时,函数内的this会被绑定到该对象上
欢迎我的公众号【小帅的编程笔记】,让我们在前端的路上越走越远