iT邦幫忙

0

Javascript 進階 5-6 最常見的 this:物件的方法調用

這篇文章要來介紹 this

終於進入重頭戲之一了喔!

this 也是讓很多開發者頭痛的地方喔,這篇文章會用簡單的方式讓大家知道,this 現在到底是誰!

那我們開始吧~

var myName = '真心鎮大冒險';

function callName () {

}

callName();

我們先這樣執行以後呢,打開 chrome 的開發者人員工具,然後選擇 Source 的 Tag,按下這個暫停的按鈕

https://ithelp.ithome.com.tw/upload/images/20200113/20121770WeBkgp1K9i.png

重新整理之後呢,我們來進入這個函式的執行堆疊~

https://ithelp.ithome.com.tw/upload/images/20200113/20121770eqb8c7kjsC.png

接著我們進入這個函式的執行堆疊之後,你就會發現 this 居然一開始就存在了

https://ithelp.ithome.com.tw/upload/images/20200113/20121770CCPsl9MU5p.png

也就是說就算不做任何事,只要函式的作用域一創建,就會有 this 這個變數。

而現在圖片中的例子呢,this 是指向全域的物件 window。

而這個 this 的指向規則,跟我們怎麼去呼叫這個函式呢有很大的關聯性。

我們先稍微調整一下程式碼~

var myName = '真心鎮大冒險';

function callName () {
    console.log(this.myName);
}

callName();

重新整理執行後就會得出 真心鎮大冒險

https://ithelp.ithome.com.tw/upload/images/20200113/20121770HMl7ySwel8.png

所以透過上方的例子你只需要了解到兩件事

  1. this 是 function 被執行的時候自帶的變數
  2. this的指向跟函式的呼叫有關

只要好好了解這篇文章的內容呢,有8成以上的this的指向你都能夠掌握

接下來就要來解釋第二點~

https://ithelp.ithome.com.tw/upload/images/20200113/20121770523w9FrYpl.png

https://ithelp.ithome.com.tw/upload/images/20200113/20121770VCCC8tuLjW.png

那麼 this 呢,是我們在執行函式的時候它自然就會產生。它不需要特別的去宣告它,就是一個保留的關鍵字。

不管是在全域的環境下,還是特定的函式中,你都可以直接調用 this

因為 this 在每個執行環境都會存在,所以很多人會誤認為 this 就是指向函式本身。

其實函式本身能夠提供的屬性有限,那通常來說我們並不會使用 this 去調用函是本身。

this 通常是指向一個可以被調用的物件,所以大家不要誤認為 this 就是指向函式本身。

https://ithelp.ithome.com.tw/upload/images/20200113/20121770bOOOpzT9eM.png

那麼我們剛剛就有說到,this的指向跟函式的呼叫有關

那麼會影響 this 的調用方式都列在下面這張圖中:

https://ithelp.ithome.com.tw/upload/images/20200113/201217708PuMeosuTO.png

  1. 作為物件方法: 這篇文章的觀念你只要掌握,通常 this 有 8 成都是運用到這個觀念。
  2. 簡易呼叫: 這個是最常見的函式呼叫方式,但是要注意,簡易呼叫不建議用運用它的 this。 在這篇文章中也會介紹甚麼是簡易呼叫?以及為什麼要避免運用簡易呼叫的 this
  3. bind apply call: 則是綁定函式到特定的 this 的方法。
  4. new: 建構式的運算子,我們之後會在原形的章節介紹到。
  5. DOM 事件處理器: 陸續會介紹到。
  6. 箭頭函式(ES6): 陸續會介紹到。

那麼 this 到底有甚麼用呢?

https://ithelp.ithome.com.tw/upload/images/20200113/20121770EE0L3xm26d.png

也就是可以透過 this 指向前面的物件。

而這邊要介紹,其實物件的方法調用是最常見的形式,這邊也是要記住兩個重點:

https://ithelp.ithome.com.tw/upload/images/20200113/20121770AGO96pzXbL.png

也就是說使用物件的方式調用的時候,你只需要關注它是在哪個物件下調用的就好!

以下面的例子來說:

https://ithelp.ithome.com.tw/upload/images/20200113/20121770xIDxK6Q2KH.png

基本上這樣執行函式的時候,後面的函式的 this 就是指向前面這個物件。

就這麼簡單,你只要掌握了這個原則就掌握了八成喔! 可喜可賀可喜可賀~

接下來呢我們來看一下範例~

範例1

var myName = '真心鎮大冒險';

function callName () {
    console.log(this.myName);
}
        
var family = {
    myName: '小明家',
    callName: callName
}

family.callName();

好,在這裡我們不管 callName 這個函式是怎麼定義的,我們只 care 它是在哪個物件下被呼叫。

因此這個 this 現在就是指向 family 這個物件。

所以很明顯透過 callName的函式印出來的結果應該是 '小明家'

https://ithelp.ithome.com.tw/upload/images/20200113/20121770dGK6vEN8hW.png

也可以多修改一下程式碼,看看 this 現在是指向誰

var myName = '真心鎮大冒險';

function callName () {
    console.log(this, this.myName);
}
        
var family = {
    myName: '小明家',
    callName: callName
}

family.callName();

https://ithelp.ithome.com.tw/upload/images/20200113/20121770wBjHEpUQKr.png

範例2

var myName = '真心鎮大冒險';

function callName () {
    console.log(this, this.myName);
}

var family = {
    myName: '小明家',
    callName: callName,
    Ming: {
        myName: '小明',
        callName: callName,
    }
}

family.callName();
family.Ming.callName();

很明顯 family.callName(); 跟剛剛一樣就會印出小明家,但第二個 family.Ming.callName(); 這個 this 指向的就是 Ming 這個物件,所以印出來的就會是小明。

https://ithelp.ithome.com.tw/upload/images/20200113/20121770fpp1OahWaU.png

範例3

var myName = '真心鎮大冒險';

function callName () {
    console.log(this.myName);
}

var family = {
    myName: '小明家',
    callName: function () {
        console.log(this.myName);
    }
}

family.callName(); // 小明家

var callName = family.callName;

callName(); // ?

那麼這邊我們可以看到 family.callName(); 這段的邏輯就是跟上面一樣, this 指向 family 的物件。

那麼如果我們今天把 family.callName 重新命名一個變數,然後在執行這個變數的話?

現在 this 會指向誰呢?

https://ithelp.ithome.com.tw/upload/images/20200113/20121770OMytfwe0NP.png

執行的結果就是 '真心鎮大冒險'

為什麼會這樣呢?

因為它被執行在全域的情況下,它的 this 就指向到了 window 的物件,所以它 console.log 出來的結果就會是 '真心鎮大冒險'喔!

這個篇文章就先解說到這裡,希望對各位有幫助! 汪汪~


尚未有邦友留言

立即登入留言