寫在前面
上一篇中,我們對於JavaScript中原始值、復雜值以及內存空間進行了一個深入淺出的總結,這次我們來聊一聊JavaScript中this關鍵字的深入淺出的用法.
在 JavaScript 中,this 是動態綁定,或稱為運行期綁定的,這就導致 JavaScript 中的 this 關鍵字有能力具備多重含義,帶來靈活性的同時,也為初學者帶來不少困惑。希望這篇文章可以解決初學者心中what’s this ?的困惑。
創建函數時,系統會在默認創建一個名為this的關鍵字,這也就是說this,只能在函數內部使用;從根本上說,由於運期綁定的特性,JavaScript中this的關鍵字要豐富的多,這完全取決於函數調用的方式:
1)作為函數調用
2)作為對象方法調用
3)使用call,apply調用
4)作為構造函數調用
我沒有按這四種調用方式依次來介紹,但是在例子中都有體現。
1、如何確定this值?
我們來看一個例子:1)當從全局域中調用sayFoo函數時,this指向window對象;2)當它作為myObject的一種方法被調用時,this引用myObject;
通過上面的例子,我們發現this 是基於調用函數的上下文的,考慮一下myObject.sayFoo和sayFoo都指向了相同的函數,然而,調用sayFoo的方式不同,this的值也不同。
通過這個例子,我們也可以體會到了a、作為函數調用;b、作為對象的方法調用時,this的不同指向
2、在嵌套函數中用this關鍵字
當在嵌套函數內部使用this時,會發生什么事呢?通過下面的例子,我們明顯看出嵌套函數內部的this都失去方向,都指向了window對象
我們在來看一種情況(原理是一樣的),我們把一個匿名函數作為參數傳遞給一個對象的方法中:,當匿名函數在foo.func1(函數內的函數)內部被調用時,匿名函數的this值同樣是window對象的引用.
3、充分利用作用域鏈研究嵌套函數的問題
JavaScript的程序員的力量是強大的,為了解決在嵌套函數內部this指向的問題,他們想出了變量代替的方法,可以簡單的在父函數使用作用域鏈來保留對this的引用,以便this不丟失。約定俗成,我們一般把變量定義為that
我們來看一個例子:
這樣,我們就很好的解決了嵌套函數內部this指向的問題
4、使用call()或apply()控制this值
我們可以通過apply()或call()來重寫/控制this值,以便定義調用函數時this指向哪個對象。“嘿,告訴x函數,調用的時候把z對象作為this值使用”,這樣做我們就可以改變JavaScript中決定this值的方式(取代默認模式)
上述代碼使用了call(),但也可以使用apply()。兩者區別在於為函數傳遞參數的方式不同:a、使用call(),參數只是使用逗號分隔的值;b、如果使用apply(),參數值在數組內傳遞。
下面使用apply可以達到同樣的效果
5、在用戶自定義構造函數內部使用this 關鍵字
在構造函數中,this默認值的變化與使用call或apply時this默認值變化不同,使用new關鍵詞調用函數時,在構造函數中聲明的this引用實例本身
在使用new關鍵詞調用構造函數時,this引用’即將創建的對象’。如果不使用new關鍵詞,this值將是調用Person的上下文 – 上例中是window對象
寫在后面
this在不同調用方式下的含義 只是JavaScript中一個很小的概念,但是也是我們借此可以深入理解JavaScript函數的執行環境,更進一步幫組我們了解閉包等其他概念,掌握了這些概念,才能充分發揮JavaScript的特點,才會發揮JavaScript語言特性的強大之處。