同事因為this指向的問題卡住的bug
,vue2的this指向問題
,使用了箭頭函數(shù),導(dǎo)致拿不到對應(yīng)的props
。當我給他介紹的時候他竟然不知道,隨後也刻意的看了一下前端交流群,至今最起碼還有70%以上的前端程式設(shè)計師搞不明白,今天給大家分享一下this
指向,如果啥都沒學(xué)會,請給我一個大嘴巴子。
1. 呼叫位置
- 作用域跟在哪裡定義有關(guān),與在哪裡執(zhí)行無關(guān)
- ##this
指向跟在哪裡定義無關(guān),跟如何調(diào)用,透過什麼樣的形式調(diào)用有關(guān)
- this
#(這個) 這個函數(shù)如何被調(diào)用(方便記憶)
#為了方便理解,預(yù)設(shè)不開啟嚴格模式
2. 綁定規(guī)則
??上面我們介紹了,this的指向主要跟透過什麼樣的形式呼叫有關(guān)。接下來我就跟大家介紹一下調(diào)用規(guī)則,沒有規(guī)矩不成方圓,大家把這幾種調(diào)用規(guī)則牢記於心就行了,沒有什麼難的地方。
- 你必須找到呼叫位置,然後判斷是下面四種的哪一種綁定規(guī)則
- #其次你要也要曉得,這四種綁定規(guī)則的優(yōu)先順序
- 這兩點你都知道了知道this的指向?qū)赌銇碚f易如反掌
#2.1 預(yù)設(shè)綁定
?? 函數(shù)最常用的呼叫方式,呼叫函數(shù)的類型:獨立函數(shù)呼叫function?bar()?{ ??console.log(this)?//?window }
- bar是不帶任何修飾符的直接呼叫所以為預(yù)設(shè)綁定為
- window
- this
為
undefined
#2.2 隱式綁定
??用最通俗的話表示就是:物件擁有某個方法,透過這個物件存取方法且直接呼叫(註:箭頭函數(shù)特殊,下面會講解)const?info?=?{ ??fullName:?'ice', ??getName:?function()?{ ????console.log(this.fullName) ??} } info.getName()?//?'ice'
- 這個函數(shù)被
- info
發(fā)起調(diào)用,進行了隱式綁定,所以當前的
this為
info,透過
this.fullName毫無疑問的就訪問值為
ice
隱含丟失普通
??有些情況下會進行隱式丟失,被隱式綁定的函數(shù)會丟失綁定對象,也就是說它為變成預(yù)設(shè)綁定,預(yù)設(shè)綁定的this值,為
window還是
undefined取決於您目前所處的環(huán)境,是否為嚴格模式。
const?info?=?{ ??fullName:?'ice', ??getName:?function()?{ ????console.log(this.fullName) ??} } const?fn?=?info.getName fn()?//undefined??這種情況下就進行了隱式丟失,丟失了綁定的對象,為什麼會產(chǎn)生這樣的問題呢?如果熟悉記憶體的小夥伴,就會很容易理解。
- 這裡並沒有直接調(diào)用,而是透過
- info
找到了對應(yīng)
getName的記憶體位址,賦值給變數(shù)
fn #然後透過 - fn
直接進行了呼叫
其實這裡的本質(zhì)就是獨立函數(shù)呼叫也就是為 - window
,從
window中取出
fullName屬性,必定為
undefined
#隱含遺失進階這裡大家首先要理解什麼是回調(diào)函數(shù)。其實可以這樣理解,就是我現(xiàn)在不呼叫它,把他透過參數(shù)的形式傳入到其他地方,在別的地方呼叫它。
//申明變量關(guān)鍵字必須為var var?fullName?=?'panpan' const?info?=?{ ??fullName:?'ice', ??getName:?function()?{ ????console.log(this.fullName) ??} } function?bar(fn)?{ ??//fn?=?info.getName ??fn()?//?panpan } bar(info.getName)
- 首先
- bar
中的
fn為一個回呼函數(shù)
- fn = info.getName
參數(shù)傳遞就是一種隱式賦值,其實跟上面的隱式遺失是一個意思,他們都是指向的
fn = info.getName引用,也就是它們的記憶體位址
因為他們的 - this
遺失,也就是函數(shù)獨立調(diào)用,預(yù)設(shè)綁定規(guī)則,
this為全域的
window物件
##注意: 為什麼申明必須為 var - 呢?
因為只有
- var
- 申明的變數(shù)才會加入到全域
window
物件上如果採用
let\const - 則不是,具體的後續(xù)介紹一下這兩個申明變數(shù)的關(guān)鍵字
- 申明的變數(shù)才會加入到全域
??但是在某些場景下,
this的改變都是意想不到的,實際上我們無法控制回呼函數(shù)的執(zhí)行方式,因此沒有辦法控制呼叫位置已得到期望的綁定即this指向。 接下來的顯示綁定就可以用來解決這個隱式遺失問題。
??js中的」所有「函數(shù)都有一些有用的特性,這個跟它的原型鏈有關(guān)係,後續(xù)我會在原型介紹,透過原型鏈js中變相實現(xiàn)繼承的方法,其中
call/apply/bind這三個方法就是函數(shù)原型鏈上的方法,可以在函數(shù)中呼叫它們。 <h4 id="strong-call-strong"><strong>2.3.2 call</strong></h4>
<ul>
<li>
<code>call()
方法使用一個指定的 this
值和單獨給出的一個或多個參數(shù)來調(diào)用一個函數(shù)。
- 第一個參數(shù)為固定綁定的
this
對象 - 第二個參數(shù)以及二以后的參數(shù),都是作為參數(shù)進行傳遞給所調(diào)用的函數(shù)
- 該方法的語法和作用與?
apply()
?方法類似,只有一個區(qū)別,就是?call()
?方法接受的是一個參數(shù)列表,而?apply()
?方法接受的是一個包含多個參數(shù)的數(shù)組。
var?fullName?=?'panpan' const?info?=?{ ??fullName:?'ice', ??getName:?function(age,?height)?{ ????console.log(this.fullName,?age,?height) ??} } function?bar(fn)?{ ??fn.call(info,?20,?1.88)?//ice?20?1.88 } bar(info.getName)
2.3.3 apply
- 與
call
的方法類似,只是參數(shù)列表有所不同- 參數(shù)
-
call
?參數(shù)為單個傳遞 -
apply
參數(shù)為數(shù)組傳遞
-
- 參數(shù)
var?fullName?=?'panpan' const?info?=?{ ??fullName:?'ice', ??getName:?function(age,?height)?{ ????console.log(this.fullName,?age,?height) ??} } function?bar(fn)?{ ??fn.apply(info,?[20,?1.88])?//ice?20?1.88 } bar(info.getName)
2.3.4 bind
-
bind
與apply/call
之間有所不同,bind
傳入this
,則是返回一個this
綁定后的函數(shù),調(diào)用返回后的函數(shù),就可以拿到期望的this。 - 參數(shù)傳遞則是
- 調(diào)用
bind
時,可以傳入?yún)?shù) - 調(diào)用
bind
返回的參數(shù)也可以進行傳參
- 調(diào)用
var?fullName?=?'panpan' const?info?=?{ ??fullName:?'ice', ??getName:?function(age,?height)?{ ????console.log(this.fullName,?age,?height)?//ice?20?1.88 ??} } function?bar(fn)?{ ??let?newFn?=?fn.bind(info,?20) ??newFn(1.88) } bar(info.getName)
2.4 new綁定
??談到new
關(guān)鍵字,就不得不談構(gòu)造函數(shù),也就是JS中的 "類",后續(xù)原型篇章在跟大家繼續(xù)探討這個new關(guān)鍵字,首先要明白以下幾點,new Fn()
的時候發(fā)生了什么,有利于我們理解this
的指向。
創(chuàng)建了一個空對象
將this指向所創(chuàng)建出來的對象
把這個對象的[[prototype]] 指向了構(gòu)造函數(shù)的prototype屬性
執(zhí)行代碼塊代碼
如果沒有明確返回一個非空對象,那么返回的對象就是這個創(chuàng)建出來的對象
function?Person(name,?age)?{ ??this.name?=?name ??this.age?=?age } const?p1?=?new?Person('ice',?20) console.log(p1)?//?{name:'ice',?age:20}
- 當我調(diào)用
new Person()
的時候,那個this所指向的其實就是p1
對象
3. 綁定優(yōu)先級
3.1 隱式綁定 > 默認綁定
function?bar()?{ ??console.log(this)?//info } const?info?=?{ ??bar:?bar } info.bar()
- 雖然這邊比較有些勉強,有些開發(fā)者會認為這是默認綁定的規(guī)則不能直接的顯示誰的優(yōu)先級高
- 但是從另外一個角度來看,隱式綁定,的this丟失以后this才會指向
widonw或者undefined
,變相的可以認為隱式綁定 > 默認綁定
3.2 顯示綁定 > 隱式綁定
var?fullName?=?'global?ice' const?info?=?{ ??fullName:?'ice', ??getName:?function()?{ ????console.log(this.fullName)? ??} } info.getName.call(this)?//global?ice info.getName.apply(this)?//global?ice info.getName.bind(this)()?//global?ice
- 通過隱式綁定和顯示綁定的一起使用很明顯 顯示綁定 > 隱式綁定
3.3 bind(硬綁定) > ?apply/call
function?bar()?{ ??console.log(this)?//123 } const?newFn?=?bar.bind(123) newFn.call(456)
3.4 new綁定 > bind綁定
首先我們來說一下,為什么是和bind
比較,而不能對call
和apply
比較,思考下面代碼
const?info?=?{ ??height:?1.88 } function?Person(name,?age)?{ ??this.name?=?name ??this.age?=?age } const?p1?=?new?Person.call('ice',?20) //報錯:?Uncaught?TypeError:?Person.call?is?not?a?constructor
new綁定和bind綁定比較
const?info?=?{ ??height:?1.88 } function?Person(name,?age)?{ ??this.name?=?name ??this.age?=?age } const?hasBindPerson?=?Person.bind(info) const?p1?=?new?hasBindPerson('ice',?20) console.log(info)?//{height:?1.88}
- 我們通過
bind
對Person
進行了一次劫持,硬綁定了this為info
對象 -
new
返回的固定this的函數(shù) - 但是我們發(fā)現(xiàn) 并不能干預(yù)this的指向
3.5 總結(jié)
new關(guān)鍵字
> bind
> apply/call
> 隱式綁定
> 默認綁定
4. 箭頭函數(shù) (arrow function)
首先箭頭函數(shù)是ES6
新增的語法
const?foo?=?()?=>?{}
4.1 箭頭函數(shù)this
var?fullName?=?'global?ice' const?info?=?{ ??fullName:?'ice', ??getName:?()?=>?{ ????console.log(this.fullName) ??} } info.getName()?//global?ice
- 你會神奇的發(fā)現(xiàn)? 為什么不是默認綁定,打印結(jié)果為
ice
- 其實這是
ES6
的新特性,箭頭函數(shù)不綁定this
,它的this
是上一層作用域,上一層作用域為window
- 所以打印的結(jié)果是
global ice
4.2 箭頭函數(shù)的應(yīng)用場景 進階
- 需求: 在
getObjName
通過this
拿到info
中的fullName
(值為ice
的fullName
)
const?info?=?{ ??fullName:?'ice', ??getName:?function()?{ ????let?_this?=?this ????return?{ ??????fullName:?'panpan', ??????getObjName:?function()?{ ????????console.log(this)?//?obj ????????console.log(_this.fullName) ??????} ????} ??} } const?obj?=?info.getName() obj.getObjName()
當我調(diào)用
info.getName()
返回了一個新對象當我調(diào)用返回對象的
getObjName
方法時,我想拿到最外層的fullName
,我通過,getObjName
的this訪問,拿到的this卻是obj
,不是我想要的結(jié)果我需要在調(diào)用
info.getName()
把this保存下來,info.getName()
是通過隱式調(diào)用,所以它內(nèi)部的this就是info對象getObjName
是obj對象,因為也是隱式綁定,this必定是obj對象,繞了一大圈我只是想拿到上層作用域的this而已,恰好箭頭函數(shù)解決了這一問題
const?info?=?{ ??fullName:?'ice', ??getName:?function()?{ ????return?{ ??????fullName:?'panpan', ??????getObjName:?()?=>?{ ????????console.log(this.fullName) ??????} ????} ??} } const?obj?=?info.getName() obj.getObjName()
5. 總結(jié)
5.1 this的四種綁定規(guī)則
默認綁定
隱式綁定
顯示綁定 apply/call/bind(也稱硬綁定)
new綁定
5.2 this的優(yōu)先級 從高到低
new綁定
bind
call/apply
隱式綁定
默認綁定
6. 結(jié)語
??當一切都看起來不起作用的時候,我就會像個石匠一樣去敲打石頭,可能敲100次,石頭沒有任何反應(yīng),但是101次,石頭可能就會裂為兩半 我知道并不是第101次起了作用,而是前面積累所致。
??大家有疑惑可以在評論區(qū)留言 第一時間為大家解答。
(學(xué)習(xí)視頻分享:web前端開發(fā))

熱AI工具

Undress AI Tool
免費脫衣圖片

Undresser.AI Undress
人工智慧驅(qū)動的應(yīng)用程序,用於創(chuàng)建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發(fā)環(huán)境

Dreamweaver CS6
視覺化網(wǎng)頁開發(fā)工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

熱門話題

WebSocket與JavaScript:實現(xiàn)即時監(jiān)控系統(tǒng)的關(guān)鍵技術(shù)引言:隨著互聯(lián)網(wǎng)技術(shù)的快速發(fā)展,即時監(jiān)控系統(tǒng)在各個領(lǐng)域中得到了廣泛的應(yīng)用。而實現(xiàn)即時監(jiān)控的關(guān)鍵技術(shù)之一就是WebSocket與JavaScript的結(jié)合使用。本文將介紹WebSocket與JavaScript在即時監(jiān)控系統(tǒng)中的應(yīng)用,並給出程式碼範例,詳細解釋其實作原理。一、WebSocket技

如何使用WebSocket和JavaScript實現(xiàn)線上語音辨識系統(tǒng)引言:隨著科技的不斷發(fā)展,語音辨識技術(shù)已成為了人工智慧領(lǐng)域的重要組成部分。而基於WebSocket和JavaScript實現(xiàn)的線上語音辨識系統(tǒng),具備了低延遲、即時性和跨平臺的特點,成為了廣泛應(yīng)用的解決方案。本文將介紹如何使用WebSocket和JavaScript來實現(xiàn)線上語音辨識系

如何利用JavaScript和WebSocket實現(xiàn)即時線上點餐系統(tǒng)介紹:隨著網(wǎng)路的普及和技術(shù)的進步,越來越多的餐廳開始提供線上點餐服務(wù)。為了實現(xiàn)即時線上點餐系統(tǒng),我們可以利用JavaScript和WebSocket技術(shù)。 WebSocket是一種基於TCP協(xié)定的全雙工通訊協(xié)議,可實現(xiàn)客戶端與伺服器的即時雙向通訊。在即時線上點餐系統(tǒng)中,當使用者選擇菜餚並下訂單

JavaScript和WebSocket:打造高效的即時天氣預(yù)報系統(tǒng)引言:如今,天氣預(yù)報的準確性對於日常生活以及決策制定具有重要意義。隨著技術(shù)的發(fā)展,我們可以透過即時獲取天氣數(shù)據(jù)來提供更準確可靠的天氣預(yù)報。在本文中,我們將學(xué)習(xí)如何使用JavaScript和WebSocket技術(shù),來建立一個高效的即時天氣預(yù)報系統(tǒng)。本文將透過具體的程式碼範例來展示實現(xiàn)的過程。 We

如何使用WebSocket和JavaScript實現(xiàn)線上預(yù)約系統(tǒng)在當今數(shù)位化的時代,越來越多的業(yè)務(wù)和服務(wù)都需要提供線上預(yù)約功能。而實現(xiàn)一個高效、即時的線上預(yù)約系統(tǒng)是至關(guān)重要的。本文將介紹如何使用WebSocket和JavaScript來實作一個線上預(yù)約系統(tǒng),並提供具體的程式碼範例。一、什麼是WebSocketWebSocket是一種在單一TCP連線上進行全雙工

JavaScript教學(xué):如何取得HTTP狀態(tài)碼,需要具體程式碼範例前言:在Web開發(fā)中,經(jīng)常會涉及到與伺服器進行資料互動的場景。在與伺服器進行通訊時,我們經(jīng)常需要取得傳回的HTTP狀態(tài)碼來判斷操作是否成功,並根據(jù)不同的狀態(tài)碼來進行對應(yīng)的處理。本篇文章將教你如何使用JavaScript來取得HTTP狀態(tài)碼,並提供一些實用的程式碼範例。使用XMLHttpRequest

用法:在JavaScript中,insertBefore()方法用於在DOM樹中插入一個新的節(jié)點。這個方法需要兩個參數(shù):要插入的新節(jié)點和參考節(jié)點(即新節(jié)點將要插入的位置的節(jié)點)。

JavaScript中的HTTP狀態(tài)碼取得方法簡介:在進行前端開發(fā)中,我們常常需要處理與後端介面的交互,而HTTP狀態(tài)碼就是其中非常重要的一部分。了解並取得HTTP狀態(tài)碼有助於我們更好地處理介面?zhèn)骰氐馁Y料。本文將介紹使用JavaScript取得HTTP狀態(tài)碼的方法,並提供具體程式碼範例。一、什麼是HTTP狀態(tài)碼HTTP狀態(tài)碼是指當瀏覽器向伺服器發(fā)起請求時,服務(wù)