您好,登錄后才能下訂單哦!
這篇文章將為大家詳細講解有關JS中this引發的bug有哪些,小編覺得挺實用的,因此分享給大家做個參考,希望大家閱讀完這篇文章后可以有所收獲。
在 js 中,this 這個上下文總是變化莫測,很多時候出現bug 總是一頭霧水,其實,只要分清楚不同的情況下如何執行就可以了,以下就是我們給大家整理的相關內容:
在JavaScript中有一個很特別、很常用又常常讓初學者很困擾的東西 ─ “this”,在這堂課中會來談談這個”this”。
this通常會指向一個對象,同時this會在不同的情境下指向不同的對象。讓我們來看幾個不同的情境,幫助我們更了解”this”。
window object (global object)
這里我們在三種不同情境去打印”this”,分別是在函數的最外層(outer environment)直接去執行;使用fuction statement去執行;使用function expression去執行(如果還不清楚function statement和function expression的差別,可以參考注1)。
結果會發現,這三個”this”都會指向同樣的對象,也就是global environment的window object (global object):
這也就是說,我們可以直接利用這個function和this在window object建立新的屬性:
在這里我們利用this.NewVariable = "..."
來在window object建立新的屬性,函數的最后,我們則可以直接console.log(NewVariable),這里之所以可以不用打this.NewVariable或window.NewVariable是因為任何在global object (window)的屬性,我們都可以直接去使用它,而不用使用”.”。
跑出來的結果會像這樣子:
它會打印出我們的”Create a new property”,同時,在window這個大的object中,我們也會找到NewVariable這個屬性:
method in object
我們知道,在對象里的值如果是原生值(primitive type;例如,字串、數值、邏輯值),我們會把這個新建立的東西稱為「屬性(property)」;如果對象里面的值是函數(function)的話,我們則會把這個新建立的東西稱為「方法(method)」。
在這里,我們就要來建立method:
首先,我們利用object literal的方式創建一個對象c,里面包含屬性name和方法log。log是一個匿名函數(anonymous function),函數內容很簡單,就是打印this而已(關于匿名函數可參考注1)。最后則是使用c.log的方式來執行該方法。
讓我們來看看,這時候的”this”會是什么呢?
答案是對象c!
當這個函數是對象里面的method時,這時候的this就會指向到包含這個method的對象
JavaScript中關于this的一個bug
讓我們更進一步延伸來看這個范例:
假設我們在method log裡面多這一行this.name = "Updated Object C name"
因為我們知道”this”現在指的是對象c,所以可以想像的,當我執行這個method的時候,它會去變更c.name的值。
這個部分是沒有什么大問題的,不過讓我們繼續看下去……。
假設我在method log裡面在做一些變更,我在這個method裡面,另外建立一個函數叫做setname,一樣是用this.name = newname
的方式來修改這個object c中name屬性的值。
接著執行setname這個函數,希望把object c中name的屬性值改成”New name for object c”,最后再去打印”this”來看一下。
結果我們會發現,對象c中name屬性的值并沒有變成”New name for object c”,竟然還是一樣!?怎么會這樣呢?
仔細一看,我們回來看一下我們的window object,我們會發現,在window object中發現了一個新的屬性”name”,而且值是”New name for object c”。
這是什么意思呢?意思是原來我們剛剛在函數setname里面的this,指向到的是global object (window object),而不再是剛剛的object C!
我們在setname這個function中,用console.log(this)來看一下:
在log這個method中,我們一共執行了三次的console.log(this)結果如下:
第一個和第三個”this”指向到的是對象c,而第二個在setname中的this,指向的則是window object (global object),而這也就是為什么setname這個function沒辦法幫我們修改對象c中name屬性的名稱,因為”this”根本沒指向到對象c。
而許多人都認為,這是JavaScript的一個bug。
那么我們可以怎么做
那么碰到上述的這個例子時,我們可以怎么做來避免指向到不同的對象呢?
許多人的解法是這樣的,因為我們知道對象都是用的引用的方式,所以我們可以這樣做
STEP 1
我們在整個函數的最上面加上一行var self = this
(有些人會用var that = this
)。由于引用的特性,self和this會指向到同一個對象,而this指向對象c,所以self一樣會指向對象c。
STEP 2
接著,把方法log內原本使用的”this”都改成”self”,這樣做可以確保self指向到的是c對象而不用擔心會像上面的例子一樣指向到錯誤的對象。
結果也如同我們預期的,在第二次console.log(self)的時候,就再次替換了對象c中name屬性的值。
總結
讓我們來總結一下:
如果我們是在全局環境建立函數并打印this,這時候this會指向到全局對象,也就是window對象。
如果我們是在對象里面創建函數,也就是方法(method)的情況時,這時候的this一般就會指向到包含這個方法的對象(之所以說”一般”是因為除了上述bug的情況之外)。
碰到method中可能會有不知道this指向到什么的情況時,為了避免不必要的錯誤,我們可以在method中的最上面建立一個變量,去把它指定成this(var self = this)。
4.如果真的還是不知道那個情況下的this會指向到什么,就console.log出來看看吧!
示例代碼
// function statement function a(){ console.log(this); this.NewVariable = "Create a new property"; } a(); console.log(NewVariable); var c = { name:"The C object", log: function(){ var self = this; self.name = "Updated object C name"; console.log(self); var setname = function(newname){ self.name = newname; console.log(self); } setname("New name for object c"); console.log(self) } } c.log();
關于“JS中this引發的bug有哪些”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,使各位可以學到更多知識,如果覺得文章不錯,請把它分享出去讓更多的人看到。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。