解析js中的this對象

前言

(幾天以前寫了源碼分析以後,感受太疲憊了,寫一些相對輕巧的內容調劑一下,但願喜歡的同窗能夠點個贊和收藏~)
進入正題,this對象在js中是很常見,可是在這裏也常常會出錯,本文將對常見的this對象的狀況作一些總結es6

正文

this對象是在函數 運行時,基於函數的執行環境綁定的。

其實這句話的本質就是,誰調用了函數,this就指向誰app

具體的來講,一般有如下幾種狀況:函數

全局函數

在全局環境中,this指向Window源碼分析

//例子1
  function A() {
    console.log(this)
  }
  A();//Window

上面的例子很簡單,函數A在全局環境中執行,也就是全局對象Window調用了函數。此時this指向Windowthis

對象方法

做爲對象方法調用時,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

call和apply

此時this對象一般指向函數中指定的this值(注意這裏的一般2字,考試要考的)

callapply算是老生常談,但仍是稍微介紹下,怕新同窗可能沒接觸過(實際上是爲了湊點字數),拿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種例外的狀況:

  1. thisArg指定爲nullundefined時,this指向window
  2. 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時,訪問進入了一種讀取模式,在後臺自動作了如下轉換:

  1. 建立一個String類型的實例
  2. 在實例上調用相應方法
  3. 銷燬該實例

特色:自動建立的基本包裝類型的對象只存在於執行代碼的瞬間,而後當即銷燬。
那麼能夠手動建立基本包裝類型嗎?固然能夠:

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

而後依然是每次都同樣的結尾,若是內容有錯誤的地方歡迎指出;若是對你有幫助,歡迎點贊和收藏,轉載請徵得贊成後著明出處,若是有問題也歡迎私信交流,主頁添加了郵箱地址~溜了

相關文章
相關標籤/搜索