5分钟彻底搞懂JavaScript中的this指向问题
theme: fancy
在Javascript中,this
的指向灵活,使用场景多,面试中会被经常提及。由于this
指向的灵活性,会在开发过程中产生一些不容易发现的BUG。
技术社区通常用一句话总结了this
的指向问题:谁调用它,this
就指向谁。也就是说,this
的指向是在调用时确定它究竟指向谁的。
通过社区的技术文章,有人总结出几条规律:
1.在函数体中非显式或隐式地简单调用函数时,在严格模式下,函数内的this会被绑定到
undefined
,在非严格模式下,则会绑定到全局对象window/global
上。 2.一般使用new方法调用构造函数时,构造函数内的this指向会被绑定到新创建的对象上。 3.一般通过call/apply/bind
方法显式调用函数时,函数体内的this会被绑定到指定参数的对象上。 4.一般通过上下文对象调用函数时,函数体内的this会被绑定到该对象上。 5.在箭头函数中,this的指向是由外层(函数或全局)作用域来决定的。
我们各点进行分析下:
全局环境中的this
非严格模式下this指向window
function f () {
console.log(this) // window
}
那么上面的代码输出则应该是window
在严格模式下函数体内的this指向undefined
```
funciton f () { 'use strict' console.log(this) //undefined } ```
通过use strict
指明严格模式的情况下 this
执行则是undefined
下面看一道题目
``` const foo = { bar: 10, fu: function() { console.log(this) console.log(this.bar) } } var fn1 = foo.fn
fn1 ()
```
fn 函数在foo对象中用来作为对象的方法,但是在赋值给fn1
之后,fn1
仍然在全局环境中执行,因此的打印结果就是
console.log(window)
console.log(window.bar)
如果把,这道题改为如下形式
const foo = {
bar: 10,
fu: function() {
console.log(this)
console.log(this.bar)
}
}
fo.fn()
则输出的是
{bar: 10, fn: f}
10
这时,this指向的是最后调用它的对象,所以this指向的是foo
对象,在执行函数时不考虑显式绑定,如果函数中的this是被上一级的对象调用,那么this指向的就是上一级的对象;否则指向全局环境。
上下文对象调用中的this
通过上面的结论我们分析下下面的代码
``` const person = { name: 'jujin', brother: { name: 'kejinan', fn: function () { return this.name } } } console.log(person.brother.fn())
``
fn 是被它的上一级调用,所以this 应该指向
brother,所以
this.name ==== 'kejinan'`
通过bind,call,apply改变this指向
用一句话总结,他们都是用来改变相关函数的this指向的,但是call和apply是直接进行函数的调用,bind不会执行相关函数,而是返回一个新的函数,并且自动绑定了新的this,需要手动调用。 用代码来总结,下面的3段代码是等价的
``` // 1 const target = {} fn.call(target, 'arg1', 'arg2')
// 2 const target = {} fn.apply(target, ['arg1', 'arg2'])
// 3 const target = {} fn.bind(taget, 'arg1', 'arg2')() ```
下面我们来分析下这道题
const foo = {
name: 'juejin',
logName: function () {
console.log(this.name)
}
}
const bar = {
name:"kejinan"
}
console.log(foo.logName.call(bar))
通过call
将this指向绑定到了bar
对象上,则输出结果是kejinan
。
构造函数和this
function Foo() {
this.bar = 'bar'
}
const instance = new Foo()
console.log(instace.bar)
执行会输出bar,需要注意的是,在构造函数中如果出现了return的情况时,可以分为两种场景:
//场景1
function Foo() {
this.user = 'juejin'
const o = {}
return o
}
const instance = new Foo()
console.log(instance.user)
执行代码则会输出undefined
,此时instance
返回的对象是控对象o.
//场景2
function Foo(){
this.user = 'juejin'
return 1
}
const instance = new Foo()
console.log(instance.user)
执行代码将会输入jueji,也就是说instance
返回的目标对象是实例this。
所以,如果构造函数中显式返回一个值,且返回的是一个对象,那么this就执行的这个返回的对象,如果返回的不是一个对象,那么this仍然指向实例。
箭头函数中的this
在箭头函数中,this指向的是由外层作用域来决定的
``` const foo = { fn: function () { setTimeout(function() { console.log(this) }) } } console.log(foo.fn())
``
在这段代码中,this出现中
setTimeout()的匿名函数中,因此this指向的是
window`对象。
如果需要让this指向foo对象,则可以用箭头函数来处理
const foo = {
fn: function () {
setTimeout(() => {
console.log(this)
})
}
}
console.log(foo.fn())
总结
通过本篇内容的学习,我们看到this的使用场景繁多,确实不容易彻底掌握。根据文中提到的5点总结再结合代码理解起来容易很多,只有死记才能用活。
参考资料
- 前端开发核心知识进阶-从夯实基础到突破瓶颈 - 侯策 - 中国工信出版集团 ISBN 978-7-121-38934-4
- 5分钟彻底搞懂JavaScript中的this指向问题
- 女主播背后,不只有“男运营”?
- 升级完少5G空间!iOS 15.4更新,戴口罩刷脸,男男怀孕表情包来了
- 男运营冒充女主播套路大哥:涉事公会官网无法访问,直播间被封
- 【高项笔记】day1.信息系统与信息化
- 长城汽车AB面:A面卖肌肉男,B面赚女人钱 | 次世代车研所
- B站“亡羊补牢式”回应男医生直播妇科手术,业内人士:用户就是免费审核员
- 小牛电动车李一男造车!“自游家”首款车型亮相
- 背叛华为被“围剿”,因744万入狱,如今又与华为同台竞技
- 背叛华为被“围剿”,因744万入狱,如今又与华为同台竞技
- 华为“高工”搅动资本江湖
- 从“小牛”到“大牛”,李一男的造车之路会顺利吗?
- 小牛创始人李一男造车进展:品牌中文名“自游家”,融资5亿美元
- 两轮大王要做四轮?小牛李一男确认:首款电动SUV明年上市
- 华为太子李一男,27岁当上副总裁身价10亿,45岁陷750万牢狱之灾
- 猥琐男躲女厕偷拍,被游戏大V抓个正着,太不要脸了
- 任正非的一个错误,为何会将李一男逼成“仇人”?西方资本的搅局
- 知名男星上海起诉!向B站up主索赔27.5万元…背后的这种技术让人害怕
- 人类高质量男?靠审丑博流量吃相实在“难看”
- 阿里涉性侵男员工曾去字节面试,已无限期终止招聘流程