(幾天以前寫了源碼分析以後,感受太疲憊了,寫一些相對輕巧的內容調劑一下,但願喜歡的同窗能夠點個贊和收藏~)
進入正題,this對象在js中是很常見,可是在這裏也常常會出錯,本文將對常見的this對象的狀況作一些總結es6
this
對象是在函數
運行時,基於函數的執行環境綁定的。
其實這句話的本質就是,誰調用了函數,this
就指向誰app
具體的來講,一般有如下幾種狀況:函數
在全局環境中,this指向Window源碼分析
//例子1 function A() { console.log(this) } A();//Window
上面的例子很簡單,函數A在全局環境中執行,也就是全局對象Window
調用了函數。此時this指向Window
this
做爲對象方法調用時,this指向調用該方法的對象code
//例子2 var b = { getThis:function(){ console.log(this) } } b.getThis()//b
到這裏咱們舉的例子都比較簡單易懂,接下來來一個有意思的:對象
//例子3 var c = { getFunc:function(){ return function(){ console.log(this) } } } var cFun = c.getFunc() cFun()//Window
這個例子和前一個例子不同,運行c.getFunc()
時,首先返回的是一個匿名函數,咱們將這個函數賦值給cFun
,接着在全局環境中調用了cFun()
,因此此時this
指向的仍是Window
。內存
若是咱們必定要讓這裏返回的是c
對象呢?在開頭咱們說過,this
對象是在函數執行時肯定的,在例子3中,執行c.getFunc()
時,this
對象指向的仍是c,因此咱們只要保持住這個this
就行了,對上面的代碼稍微改動:字符串
//例子4 var c = { getFunc:function(){ var that = this //在這裏保留住this return function(){ console.log(that) } } } var cFun = c.getFunc() cFun()//c
這也就是咱們常常能夠在一些代碼中看到var self = this
或者var that = this
之類的緣由了。get
此時this對象一般指向函數中指定的this值(注意這裏的一般2字,考試要考的)
call
和apply
算是老生常談,但仍是稍微介紹下,怕新同窗可能沒接觸過(實際上是爲了湊點字數),拿call
來講,語法是這樣的
fun.call(thisArg, arg1, arg2, ...)
這個方法怎麼用呢,看下面的例子:
//例子5 var d = { getThis:function(){ console.log(this) } } var e = { name:'e'//(給e寫個`name`屬性只是由於以爲孤零零的太難看了~~) } d.getThis.call(e)//e
在這裏咱們就能夠看出call函數的意思了:指定一個對象o1
去調用其餘對象o2
的方法,此時this
對象指向o1
好了,那爲何前面咱們說一般呢?由於,有2種例外的狀況:
thisArg
指定爲null
和undefined
時,this
指向window
。thisArg
指定爲原始值(數字,字符串,布爾值),this
會指向該原始值的自動包裝對象(這一點感謝評論區的讀者補充)。請看://例子6 var d = { getThis:function(){ console.log(this) } } d.getThis.call(null)//Window d.getThis.call(undefined)//Window d.getThis.call(1) //Number d.getThis.call("hello") //String d.getThis.call(true) //Boolean
既然講到包裝類型,那這裏順便補充介紹一下基本包裝類型:基本包裝類型(包括Boolean,String,Number)是一類特殊的引用類型,它們具備引用類型的基本特徵,還具備對應的基本類型的特殊行爲,舉個例子:
//基本包裝類型 var str = "hello World"; var str2 = s1.substring(2);
首先,str
是字符串,字符串是基本數據類型,可是在第二行代碼中,str.substring(2)
調用了str
的方法,咱們知道,基本數據類型不是對象,原本是是不該該有方法的,可是實際上咱們知道string,number類型都有對應的方法,由於從內存中訪問str時,訪問進入了一種讀取模式,在後臺自動作了如下轉換:
String
類型的實例特色:自動建立的基本包裝類型的對象只存在於執行代碼的瞬間,而後當即銷燬。
那麼能夠手動建立基本包裝類型嗎?固然能夠:
var str = new String("Hello")//注意這裏是new一個實例,而不是用String類型轉換函數 typeof(str)//object var str2 = String(222)//若是使用類型轉換函數獲得的仍是類型 ypeof(str2)//string
此時的str
就是一個顯式建立的基本包裝類型對象,只是通常來講不多這樣去使用
es6中的箭頭函數如今也用的比較頻繁,可是有個須要注意的點是:
函數體內的this對象,就是定義時所在的對象,而不是使用時所在的對象。
其實出現這種狀況的根本緣由是:箭頭函數沒有this對象,因此箭頭函數的this就是外層代碼的this
//例子7 var f = { getThis:()=>{ console.log(this) } } f.getThis()//Window
這個例子和前面例子2是基本同樣的,只是把普通函數改寫成箭頭函數,可是此時的this對象已經指向了外層的Window
。
考慮到這一點可能很差理解,咱們再看幾個例子:
//例子8 var g = { getThis:function(){ return function(){console.log(this)} } } var h = { getThis:function(){ return ()=> console.log(this) } } g.getThis()()//Window h.getThis()()//h
這個例子裏,g的getThis
寫法就和以前的例子3同樣,因爲函數在全局環境中運行,因此此時this
指向Window
;h的getThis
使用了箭頭函數,因此this指向了外層代碼塊的this因此,此時this
指向的是h。
小結一下,
this
對象指向調用函數的對象,全局環境中執行函數this
對象指向Window
call和apply
函數中this
指向指定的對象,若是指定的對爲undefined
或者null
,那麼this
對象指向Window
this
對象等同於外層代碼塊的this
而後依然是每次都同樣的結尾,若是內容有錯誤的地方歡迎指出;若是對你有幫助,歡迎點贊和收藏,轉載請徵得贊成後著明出處,若是有問題也歡迎私信交流,主頁添加了郵箱地址~溜了