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萬元…背後的這種技術讓人害怕
- 人類高質量男?靠審醜博流量吃相實在“難看”
- 阿里涉性侵男員工曾去位元組面試,已無限期終止招聘流程