An article that understands this point and catches up with 70% of front-end people
Sep 06, 2022 pm 05:03 PMColleagues got stuck because of the problem pointed by thisbug
, vue2’s this pointed problem
, using the arrow function, resulting in the inability to get the corresponding props
. He didn't know it when I introduced it to him, and then I deliberately looked at the front-end communication group. So far, at least 70% of front-end programmers still don't understand it. I'll share it with you today this
Point, if you haven’t learned anything, please give me a big mouth.
1. Calling location
- The scope is related to where it is defined and has nothing to do with where it is executed
-
this
The pointer has nothing to do with where it is defined, it has to do with how it is called and in what form -
this
(this) how this function is called (convenient to remember) - In order to facilitate understanding, strict mode is not enabled by default
2. Binding rules
We introduced above,this
Pointing mainly depends on the form of calling. Next, I will introduce the calling rules to you. Without rules, nothing is complete. Just keep these calling rules in mind. There is nothing difficult.
- You must find the calling location, and then determine which of the following four binding rules is
- Secondly, you must also know the priority of these four binding rules.
- You know these two points and it will be easy for you to know where this points.
2.1 Default binding
Functions are the most commonly used The calling method, the type of calling function: independent function call
function?bar()?{ ??console.log(this)?//?window }
- bar is a direct call without any modifier, so the default binding is
window
- In strict mode,
this
here isundefined
##2.2 Implicit binding
Use the most In layman's terms, it means: the object has a certain method, and the method is accessed through this object and called directly (note: the arrow function is special, which will be explained below)const?info?=?{ ??fullName:?'ice', ??getName:?function()?{ ????console.log(this.fullName) ??} } info.getName()?//?'ice'
- This function is
- info
The call is initiated and implicit binding is performed, so the current
thisis
info, and the value accessed through
this.fullNameis undoubtedly
ice
Implicit loss normal
? In some cases, implicit loss will be performed, and the implicitly bound function will lose the bound object. , that is to say, it becomes the default binding. Thethis value of the default binding is
window or
undefined, depending on the environment you are currently in. Whether it is strict mode.
const?info?=?{ ??fullName:?'ice', ??getName:?function()?{ ????console.log(this.fullName) ??} } const?fn?=?info.getName fn()?//undefined??In this case, implicit loss is performed and the bound object is lost. Why does such a problem occur? If you are familiar with memory, it will be easy to understand.
- There is no direct call here, but the memory address corresponding to
- getName
is found through
infoand assigned to the variable
fn Then the call was made directly through - fn
- window
, from
windowTake out the
fullNameattribute, which must be
undefined
Implicit loss advancedWhat do you need to understand first? Is the callback function. In fact, it can be understood this way, that is, I don't call it now, but pass it to other places in the form of parameters, and call it somewhere else.
//申明變量關(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)
- First of all,
- fn
in
baris a callback function
- fn = info.getName
parameter passing It is an implicit assignment. In fact, it has the same meaning as the implicit loss above. They all point to
fn = info.getNamereferences, which is their memory addresses
because they The - this
is lost, that is, the function is called independently, the default binding rule is,
thisis the global
windowobject
Note: Why must the declaration be What about - var
?
- Because only the variables declared by
- var
will be added to the global
windowobject
If - let\const
is used, then No, I will introduce the two keywords for declaring variables in detail
But in some scenarios, I don’t want implicit loss. What should I do? Let’s introduce display binding to you. , that is, fixed call. - var
2.3 Display binding
?However, in some scenarios, the changes inthis are unexpected. In fact, we There is no control over how the callback function is executed, so there is no way to control that the calling location has the expected binding that this points to.
2.3.1 call/apply/bind
“All” functions in js have some useful features. This is related to its prototype chain. Follow-up I will introduce in the prototype, the method of implementing inheritance in disguise through the prototype chain js, among which the three methodscall/apply/bind are the methods on the function prototype chain, and they can be called in the function.
2.3.2 call
-
call()
方法使用一個(gè)指定的this
值和單獨(dú)給出的一個(gè)或多個(gè)參數(shù)來(lái)調(diào)用一個(gè)函數(shù)。- 第一個(gè)參數(shù)為固定綁定的
this
對(duì)象 - 第二個(gè)參數(shù)以及二以后的參數(shù),都是作為參數(shù)進(jìn)行傳遞給所調(diào)用的函數(shù)
- 第一個(gè)參數(shù)為固定綁定的
- 備注
- 該方法的語(yǔ)法和作用與?
apply()
?方法類似,只有一個(gè)區(qū)別,就是?call()
?方法接受的是一個(gè)參數(shù)列表,而?apply()
?方法接受的是一個(gè)包含多個(gè)參數(shù)的數(shù)組。
- 該方法的語(yǔ)法和作用與?
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ù)為單個(gè)傳遞 -
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
,則是返回一個(gè)this
綁定后的函數(shù),調(diào)用返回后的函數(shù),就可以拿到期望的this。 - 參數(shù)傳遞則是
- 調(diào)用
bind
時(shí),可以傳入?yún)?shù) - 調(diào)用
bind
返回的參數(shù)也可以進(jìn)行傳參
- 調(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ù)探討這個(gè)new關(guān)鍵字,首先要明白以下幾點(diǎn),new Fn()
的時(shí)候發(fā)生了什么,有利于我們理解this
的指向。
創(chuàng)建了一個(gè)空對(duì)象
將this指向所創(chuàng)建出來(lái)的對(duì)象
把這個(gè)對(duì)象的[[prototype]] 指向了構(gòu)造函數(shù)的prototype屬性
執(zhí)行代碼塊代碼
如果沒(méi)有明確返回一個(gè)非空對(duì)象,那么返回的對(duì)象就是這個(gè)創(chuàng)建出來(lái)的對(duì)象
function?Person(name,?age)?{ ??this.name?=?name ??this.age?=?age } const?p1?=?new?Person('ice',?20) console.log(p1)?//?{name:'ice',?age:20}
- 當(dāng)我調(diào)用
new Person()
的時(shí)候,那個(gè)this所指向的其實(shí)就是p1
對(duì)象
3. 綁定優(yōu)先級(jí)
3.1 隱式綁定 > 默認(rèn)綁定
function?bar()?{ ??console.log(this)?//info } const?info?=?{ ??bar:?bar } info.bar()
- 雖然這邊比較有些勉強(qiáng),有些開(kāi)發(fā)者會(huì)認(rèn)為這是默認(rèn)綁定的規(guī)則不能直接的顯示誰(shuí)的優(yōu)先級(jí)高
- 但是從另外一個(gè)角度來(lái)看,隱式綁定,的this丟失以后this才會(huì)指向
widonw或者undefined
,變相的可以認(rèn)為隱式綁定 > 默認(rèn)綁定
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
- 通過(guò)隱式綁定和顯示綁定的一起使用很明顯 顯示綁定 > 隱式綁定
3.3 bind(硬綁定) > ?apply/call
function?bar()?{ ??console.log(this)?//123 } const?newFn?=?bar.bind(123) newFn.call(456)
3.4 new綁定 > bind綁定
首先我們來(lái)說(shuō)一下,為什么是和bind
比較,而不能對(duì)call
和apply
比較,思考下面代碼
const?info?=?{ ??height:?1.88 } function?Person(name,?age)?{ ??this.name?=?name ??this.age?=?age } const?p1?=?new?Person.call('ice',?20) //報(bào)錯(cuò):?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}
- 我們通過(guò)
bind
對(duì)Person
進(jìn)行了一次劫持,硬綁定了this為info
對(duì)象 -
new
返回的固定this的函數(shù) - 但是我們發(fā)現(xiàn) 并不能干預(yù)this的指向
3.5 總結(jié)
new關(guān)鍵字
> bind
> apply/call
> 隱式綁定
> 默認(rèn)綁定
4. 箭頭函數(shù) (arrow function)
首先箭頭函數(shù)是ES6
新增的語(yǔ)法
const?foo?=?()?=>?{}
4.1 箭頭函數(shù)this
var?fullName?=?'global?ice' const?info?=?{ ??fullName:?'ice', ??getName:?()?=>?{ ????console.log(this.fullName) ??} } info.getName()?//global?ice
- 你會(huì)神奇的發(fā)現(xiàn)? 為什么不是默認(rèn)綁定,打印結(jié)果為
ice
- 其實(shí)這是
ES6
的新特性,箭頭函數(shù)不綁定this
,它的this
是上一層作用域,上一層作用域?yàn)?code>window - 所以打印的結(jié)果是
global ice
4.2 箭頭函數(shù)的應(yīng)用場(chǎng)景 進(jìn)階
- 需求: 在
getObjName
通過(guò)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()
當(dāng)我調(diào)用
info.getName()
返回了一個(gè)新對(duì)象當(dāng)我調(diào)用返回對(duì)象的
getObjName
方法時(shí),我想拿到最外層的fullName
,我通過(guò),getObjName
的this訪問(wèn),拿到的this卻是obj
,不是我想要的結(jié)果我需要在調(diào)用
info.getName()
把this保存下來(lái),info.getName()
是通過(guò)隱式調(diào)用,所以它內(nèi)部的this就是info對(duì)象getObjName
是obj對(duì)象,因?yàn)橐彩请[式綁定,this必定是obj對(duì)象,繞了一大圈我只是想拿到上層作用域的this而已,恰好箭頭函數(shù)解決了這一問(wèn)題
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ī)則
默認(rèn)綁定
隱式綁定
顯示綁定 apply/call/bind(也稱硬綁定)
new綁定
5.2 this的優(yōu)先級(jí) 從高到低
new綁定
bind
call/apply
隱式綁定
默認(rèn)綁定
6. 結(jié)語(yǔ)
??當(dāng)一切都看起來(lái)不起作用的時(shí)候,我就會(huì)像個(gè)石匠一樣去敲打石頭,可能敲100次,石頭沒(méi)有任何反應(yīng),但是101次,石頭可能就會(huì)裂為兩半 我知道并不是第101次起了作用,而是前面積累所致。
??大家有疑惑可以在評(píng)論區(qū)留言 第一時(shí)間為大家解答。
(學(xué)習(xí)視頻分享:web前端開(kāi)發(fā))

Hot AI Tools

Undress AI Tool
Undress images for free

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Clothoff.io
AI clothes remover

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

Hot Topics

WebSocket and JavaScript: Key technologies for realizing real-time monitoring systems Introduction: With the rapid development of Internet technology, real-time monitoring systems have been widely used in various fields. One of the key technologies to achieve real-time monitoring is the combination of WebSocket and JavaScript. This article will introduce the application of WebSocket and JavaScript in real-time monitoring systems, give code examples, and explain their implementation principles in detail. 1. WebSocket technology

How to use WebSocket and JavaScript to implement an online speech recognition system Introduction: With the continuous development of technology, speech recognition technology has become an important part of the field of artificial intelligence. The online speech recognition system based on WebSocket and JavaScript has the characteristics of low latency, real-time and cross-platform, and has become a widely used solution. This article will introduce how to use WebSocket and JavaScript to implement an online speech recognition system.

Introduction to how to use JavaScript and WebSocket to implement a real-time online ordering system: With the popularity of the Internet and the advancement of technology, more and more restaurants have begun to provide online ordering services. In order to implement a real-time online ordering system, we can use JavaScript and WebSocket technology. WebSocket is a full-duplex communication protocol based on the TCP protocol, which can realize real-time two-way communication between the client and the server. In the real-time online ordering system, when the user selects dishes and places an order

JavaScript and WebSocket: Building an efficient real-time weather forecast system Introduction: Today, the accuracy of weather forecasts is of great significance to daily life and decision-making. As technology develops, we can provide more accurate and reliable weather forecasts by obtaining weather data in real time. In this article, we will learn how to use JavaScript and WebSocket technology to build an efficient real-time weather forecast system. This article will demonstrate the implementation process through specific code examples. We

How to use WebSocket and JavaScript to implement an online reservation system. In today's digital era, more and more businesses and services need to provide online reservation functions. It is crucial to implement an efficient and real-time online reservation system. This article will introduce how to use WebSocket and JavaScript to implement an online reservation system, and provide specific code examples. 1. What is WebSocket? WebSocket is a full-duplex method on a single TCP connection.

JavaScript tutorial: How to get HTTP status code, specific code examples are required. Preface: In web development, data interaction with the server is often involved. When communicating with the server, we often need to obtain the returned HTTP status code to determine whether the operation is successful, and perform corresponding processing based on different status codes. This article will teach you how to use JavaScript to obtain HTTP status codes and provide some practical code examples. Using XMLHttpRequest

Usage: In JavaScript, the insertBefore() method is used to insert a new node in the DOM tree. This method requires two parameters: the new node to be inserted and the reference node (that is, the node where the new node will be inserted).

Introduction to the method of obtaining HTTP status code in JavaScript: In front-end development, we often need to deal with the interaction with the back-end interface, and HTTP status code is a very important part of it. Understanding and obtaining HTTP status codes helps us better handle the data returned by the interface. This article will introduce how to use JavaScript to obtain HTTP status codes and provide specific code examples. 1. What is HTTP status code? HTTP status code means that when the browser initiates a request to the server, the service