JavaScript?執(zhí)行上下文的視角詳解this使用
前言
在對象內部的方法中使用對象內部的屬性是一個非常普遍的需求。但是 JavaScript 的作用域機制并不支持這一點,基于這個需求,JavaScript 有另外一套 this 機制。
this 是和執(zhí)行上下文綁定的,也就是說每個執(zhí)行上下文中都有一個 this。執(zhí)行上下文主要分為三種——全局執(zhí)行上下文、函數(shù)執(zhí)行上下文和 eval 執(zhí)行上下文,所以對應的 this 也只有這三種——全局執(zhí)行上下文中的 this、函數(shù)中的 this 和 eval 中的 this。
全局執(zhí)行上下文中的 this
全局執(zhí)行上下文中的 this 是指向 window 對象的。這也是 this 和作用域鏈的 唯一交點,作用域鏈的最底端包含了 window 對象,全局執(zhí)行上下文中的 this 也是指向 window 對象。
函數(shù)執(zhí)行上下文中的 this
function foo() {
console.log(this);
}
foo();
執(zhí)行這段代碼,打印出來的也是 window 對象,這說明在默認情況下調用一個函數(shù),其執(zhí)行上下文中的 this 也是指向 window 對象的。
通常情況下,有下面三種方式來設置函數(shù)執(zhí)行上下文中的 this 值:
1. 通過函數(shù)的 call 方法設置
let bar = {
myName: "極客邦",
test1: 1,
};
function foo() {
this.myName = "極客時間";
}
foo.call(bar);
console.log(bar);
console.log(myName);
執(zhí)行這段代碼,你就能發(fā)現(xiàn) foo 函數(shù)內部的 this 已經(jīng)指向了 bar 對象,因為通過打印 bar 對象,可以看出 bar 的 myName 屬性已經(jīng)由“極客邦”變?yōu)?ldquo;極客時間”了,同時在全局執(zhí)行上下文中打印 myName,JavaScript 引擎提示該變量未定義。其實除了 call 方法,你還可以使用 bind 和 apply 方法來設置函數(shù)執(zhí)行上下文中的 this。
2. 通過對象調用方法設置
var myObj = {
name: "極客時間",
showThis: function () {
console.log(this);
},
};
myObj.showThis();
執(zhí)行這段代碼,你可以看到,最終輸出的 this 值是指向 myObj 的。所以,你可以得出這樣的結論:使用對象來調用其內部的一個方法,該方法的 this 是指向對象本身的。
接下來我們稍微改變下調用方式,把 showThis 賦給一個全局對象,然后再調用該對象,代碼如下所示:
var myObj = {
name: "極客時間",
showThis: function () {
this.name = "極客邦";
console.log(this);
},
};
var foo = myObj.showThis;
foo();
執(zhí)行這段代碼,你會發(fā)現(xiàn) this 又指向了全局 window 對象。
結論:
在全局環(huán)境中調用一個函數(shù),函數(shù)內部的 this 指向的是全局變量 window。
通過一個對象來調用其內部的一個方法,該方法的執(zhí)行上下文中的 this 指向對象本身。
3. 通過構造函數(shù)中設置
function CreateObj() {
this.name = "極客時間";
}
var myObj = new CreateObj();
當執(zhí)行 new CreateObj() 的時候,JavaScript 引擎做了如下四件事:
首先創(chuàng)建了一個空對象 tempObj
接著調用 CreateObj.call 方法,并將 tempObj 作為 call 方法的參數(shù),這樣當 CreateObj 的執(zhí)行上下文創(chuàng)建時,它的 this 就指向了 tempObj 對象
然后執(zhí)行 CreateObj 函數(shù),此時的 CreateObj 函數(shù)執(zhí)行上下文中的 this 指向了 tempObj 對象
最后返回 tempObj 對象
var tempObj = {};
CreateObj.call(tempObj);
return tempObj;
這樣,就通過 new 關鍵字構建好了一個新對象,并且構造函數(shù)中的 this 其實就是新對象本身。
this 的設計缺陷以及應對方案
1. 嵌套函數(shù)中的 this 不會從外層函數(shù)中繼承
var myObj = {
name: "極客時間",
showThis: function () {
console.log(this);
function bar() {
console.log(this);
}
bar();
},
};
myObj.showThis();
執(zhí)行這段代碼后,會發(fā)現(xiàn)函數(shù) bar 中的 this 指向的是全局 window 對象,而函數(shù) showThis 中的 this 指向的是 myObj 對象。
可以通過一個小技巧來解決這個問題,比如在 showThis 函數(shù)中聲明一個變量 that 用來保存 this,然后在 bar 函數(shù)中使用 that。其實,這個方法的的本質是把 this 體系轉換為了作用域的體系。
其實,你也可以使用 ES6 中的箭頭函數(shù)來解決這個問題:
var myObj = {
name: "極客時間",
showThis: function () {
console.log(this);
var bar = () => {
console.log(this);
};
bar();
},
};
myObj.showThis();
這是因為 ES6 中的箭頭函數(shù)并不會創(chuàng)建其自身的執(zhí)行上下文,所以箭頭函數(shù)中的 this 取決于它的外部函數(shù)。
2. 普通函數(shù)中的 this 默認指向全局對象 window
在實際工作中,我們并不希望函數(shù)執(zhí)行上下文中的 this 默認指向全局對象,因為這樣會打破數(shù)據(jù)的邊界,造成一些誤操作。如果要讓函數(shù)執(zhí)行上下文中的 this 指向某個對象,最好的方式是通過 call 方法來顯示調用。
可以通過設置 JavaScript 的 嚴格模式 來解決(在第一行加上 "use strict";)。在嚴格模式下,默認執(zhí)行一個函數(shù),其函數(shù)的執(zhí)行上下文中的 this 值是 undefined。
以上就是JavaScript 執(zhí)行上下文的視角詳解this使用的詳細內容,更多關于JavaScript 執(zhí)行上下文 this的資料請關注腳本之家其它相關文章!
相關文章
WindiCSS實現(xiàn)加載windi.config.ts配置文件詳解
這篇文章主要為大家介紹了WindiCSS實現(xiàn)加載windi.config.ts配置文件詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-02-02
微信小程序 出現(xiàn)錯誤:{"baseresponse":{"errcode":-80002,"errmsg":""}}解決
這篇文章主要介紹了微信小程序 出現(xiàn)錯誤:{"baseresponse":{"errcode":-80002,"errmsg":""}}解決辦法的相關資料,需要的朋友可以參考下2017-02-02

