JavaScript中this指向的最全總結(jié)
前言
- 前端的初學(xué)者在學(xué)習(xí)Javascript中this指向的時候經(jīng)常都會一頭霧水,尤其是在ES6箭頭函數(shù)出現(xiàn)之前。
- this指向之所以容易讓人頭疼,原因在于 this 是在代碼執(zhí)行時根據(jù)環(huán)境和情況不同才決定綁定為什么值。
- 所以本篇文章主要是介紹和總結(jié)了各種情況下的this指向,如果文中有寫的不對的地方或者明顯錯誤,還請不吝指出互相交流。
在開始之前,還是需要介紹this的一些基礎(chǔ)知識,具體如下:
- this 是javascript中的一個關(guān)鍵字,并非是一個變量。
- this 關(guān)鍵字指向的是一個對象,而指向哪個對象,或者是這個對象的值是什么取決于使用(調(diào)用)的方式和環(huán)境。
- this 指向的值是可以通過手動方式去改變的,比如call、bind、apply方法。
- this 在嚴(yán)格模式和非嚴(yán)格模式下也會有差別。
一、全局普通函數(shù)
非嚴(yán)格模式下,全局普通函數(shù)的this指向 window
var a = 0; // 相當(dāng)于window.a = 0 function testWindow() { this.a = 1; //相當(dāng)于window.a console.log(this.a); //1 console.log(window.a); // 1 console.log(this); //Window {postMessage: ?, blur: ?, focus: ?, close: ?, frames: Window, …} } testWindow();
嚴(yán)格模式下,普通函數(shù)的this指向undefined
var a = 1; function testStrict() { "use strict"; console.log(this); //undefined console.log(this.a); // Uncaught TypeError: Cannot read property 'a' of undefined } testStrict();
二、對象的函數(shù)方法
// 不管是嚴(yán)格模式還是非嚴(yán)格模式,調(diào)用對象的函數(shù)方法時,被調(diào)用函數(shù)中的this永遠(yuǎn)指向這個對象 var a = 2; var obj = { a: 1, b: function () { console.log(this); //{a: 1, b: ?} console.log(this.a); //1 } }; obj.b();
做一個小練習(xí)題,將上面的代碼進(jìn)行一個簡單的變化:
var a = 2; var obj = { a: 1, b: function () { console.log(this); // indow {window: Window, self: Window, …} console.log(this.a); // 2 } }; var foo = obj.b; foo(); // 相當(dāng)于window.foo()
為什么這個時候this是指向了window呢?
我們在開頭說過,對象中函數(shù)調(diào)用,this是指向調(diào)用這個函數(shù)的對象。
foo變量接收了obj對象中的b函數(shù),并且在全局作用域下執(zhí)行,其實(shí)就相當(dāng)于window.foo(),
那么自然就變成了第一種情況:全局作用域下普通函數(shù)調(diào)用指向window(非嚴(yán)格模式下)
三、構(gòu)造函數(shù)
//不管是嚴(yán)格模式還是非嚴(yán)格模式,構(gòu)造函數(shù)中的this都是指向構(gòu)造函數(shù)創(chuàng)建的對象實(shí)例 function Test(a) { this.a = a; console.log(this.a); //1 } Test.prototype.say = function () { console.log(this); //test {a: 1} console.log(this.a); //1 }; var t = new test(1); console.log(t); //test {a: 1} t.say();
四、事件處理函數(shù)
<body> <button id="btn">click</button> <button id="btn1">click1</button> <script> /** * this指向被綁定的目標(biāo)對象 * */ var btn = document.getElementById("btn"); btn.onclick = function () { console.log(this); // <button id="btn">click</button> this.innerHTML = "loading.."; this.disabled = true; }; var btn1 = document.getElementById("btn1"); btn1.onclick = () => { console.log(this); //window }; </script> </body>
五、內(nèi)聯(lián)函數(shù)
以下代碼包含了嚴(yán)格模式和非嚴(yán)格模式不同的情況。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Document</title> </head> <body> <button onclick=" alert(this);">內(nèi)聯(lián)事件處理0</button> //元素本身即button <button onclick="alert((function(){'use strict'; return this})());">內(nèi)聯(lián)事件處理1</button> //undefined <button onclick="alert((function(){ return this})());">內(nèi)聯(lián)事件處理2</button> //window <button onclick="'use strict'; alert(this.tagName.toLowerCase());">內(nèi)聯(lián)事件處理3</button> //button </body> </html>
六、全局作用域
全局作用域下就比較簡單了,直接記住就好。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Document</title> </head> <body> <script> /** * 不管是嚴(yán)格模式還是不是嚴(yán)格模式this都指向window * */ "use strict"; console.log(this); // window </script> </body> </html>
值得擴(kuò)展的一點(diǎn)是,不同環(huán)境下的全局對象是不一樣的
- 瀏覽器web: window,self,frames
- node環(huán)境下: global
- web worker : self
而在ES2020中,最終定義了 globalThis 作為在任何上下文中引用全局對象的標(biāo)準(zhǔn)方式。2020年初,所有現(xiàn)代瀏覽器和Node都實(shí)現(xiàn)了這個特性,具體詳細(xì)可以參考:mdn web_docs
七、箭頭函數(shù)
我們這里把箭頭函數(shù)單獨(dú)拿出來總結(jié),在ES6中箭頭函數(shù)的出現(xiàn)大大改善了this指向的‘繁瑣’情況:
- 箭頭函數(shù)自身沒有this;
- 箭頭函數(shù)的this不是調(diào)用的時候決定的,而是在定義的時候所處的環(huán)境就已經(jīng)決定了。
- 技巧: 箭頭函數(shù)的this看外層是否有函數(shù)
- 1).如果有,外層函數(shù)的this就是內(nèi)部箭頭函數(shù)的this
- 2).如果沒有,this就是window.
普通的箭頭函數(shù)在全局環(huán)境下始終指向window
let testES6 = () => { console.log(this); //Window {postMessage: ?, blur: ?, focus: ?, close: ?, frames: Window, …} }; testES6(); let testES6Strict = () => { "use strict"; console.log(this); //Window {postMessage: ?, blur: ?, focus: ?, close: ?, frames: Window, …} }; testES6Strict();
對象的箭頭函數(shù)中,this則是指向執(zhí)行該對象所處的執(zhí)行上下文(執(zhí)行環(huán)境)
var obj = { fun: () => { console.log(this); // Window {postMessage: ?, blur: ?, focus: ?, close: ?, frames: Window, …} } }; obj.fun(); // fun箭頭函數(shù)外層沒有函數(shù),指向window var obj = { fun: () => { "use strict"; console.log(this); // Window {postMessage: ?, blur: ?, focus: ?, close: ?, frames: Window, …} } }; obj.fun();
事件處理中的箭頭函數(shù)中,this指向window
<html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Document</title> </head> <body> <button id="btn1">click1</button> <script> var btn1 = document.getElementById("btn1"); btn1.onclick = () => { console.log(this); //window }; </script> </body> </html>
以上就是JavaScript中this指向的最全總結(jié)的詳細(xì)內(nèi)容,更多關(guān)于JavaScript this指向的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
小程序?qū)崿F(xiàn)人臉識別的項(xiàng)目實(shí)踐
人臉識別在現(xiàn)在很多地方都可以用的到,例如支付,解鎖等,本文就來介紹一下小程序?qū)崿F(xiàn)人臉識別,具有一定的參考價值,感興趣的可以了解一下2023-10-10js實(shí)現(xiàn)增加數(shù)字顯示的環(huán)形進(jìn)度條效果
本文主要分享了js實(shí)現(xiàn)增加數(shù)字顯示的環(huán)形進(jìn)度條效果的示例代碼。具有一定的參考價值,下面跟著小編一起來看下吧2017-02-02JS實(shí)現(xiàn)點(diǎn)擊循環(huán)切換顯示內(nèi)容的方法
這篇文章主要介紹了JS實(shí)現(xiàn)點(diǎn)擊循環(huán)切換顯示內(nèi)容的方法,涉及javascript鼠標(biāo)事件響應(yīng)及頁面元素的獲取、屬性設(shè)置等相關(guān)操作技巧,需要的朋友可以參考下2017-10-10js實(shí)現(xiàn)的鼠標(biāo)滾輪滾動切換頁面效果(類似360默認(rèn)頁面滾動切換效果)
這篇文章主要介紹了js實(shí)現(xiàn)的鼠標(biāo)滾輪滾動切換頁面效果,類似360默認(rèn)頁面滾動切換效果.涉及JavaScript響應(yīng)鼠標(biāo)事件動態(tài)變換頁面元素的相關(guān)技巧,需要的朋友可以參考下2016-01-01