前言
this 是讓很多開發者頭痛的地方,這篇文章會用簡單的方式讓大家知道,this 現在到底是誰 !
this 是 function 被執行的時候自帶的變數
var myName = '真心鎮大冒險';
function callName () {
}
callName();
我們先這樣執行以後,打開 chrome 的開發者人員工具,然後選擇 Source 的 Tag,按下這個暫停的按鈕
重新整理之後呢,我們來進入這個函式的執行堆疊
接著我們進入這個函式的執行堆疊之後,你就會發現 this 居然一開始就存在了
也就是說就算不做任何事,只要函式的作用域一創建,就會有 this 這個變數。
而現在圖片中的例子呢,this 是指向全域的物件 window
而這個 this 的指向規則,跟我們怎麼去呼叫這個函式有很大的關聯性
我們先稍微調整一下程式碼
var myName = '真心鎮大冒險';
function callName () {
console.log(this.myName);
}
callName(); // 真心鎮大冒險
所以透過上方的例子你只需要了解到兩件事
- this 是 function 被執行的時候自帶的變數
- this的指向跟函式的呼叫有關
this
this 是我們在執行函式的時候它自然就會產生,不需要特別的去宣告它,就是一個保留的關鍵字。不管是在全域的環境下,
還是特定的函式中,你都可以直接調用 this,因為 this 在每個執行環境都會存在,所以很多人會誤認為 this 就是指向函式
本身。
其實函式本身能夠提供的屬性有限,那通常來說我們並不會使用 this 去調用函是本身,而 this 通常是指向一個可以被調用
的物件,所以大家不要誤認為 this 就是指向函式本身。
this基本觀念
- 每個執行環境都有屬於自己的
this關鍵字 this與函式如何宣告沒有關聯性,僅與呼叫方法有關- 嚴格模式下,簡易呼叫會有很大的改變
那麼我們剛剛就有說到,this 的指向跟函式的呼叫有關
影響 this 的調用方式有哪些
- 作為物件方法 (最常運用
this方法)
這篇文章的觀念你只要掌握,通常
this有 8 成都是運用到這個觀念
- 簡易呼叫 (絕大多數的呼叫方式)
這個是最常見的函式呼叫方式,但是要注意,簡易呼叫不建議用運用它的
this。
在這篇文章中也會介紹什麼是簡易呼叫?以及為什麼要避免運用簡易呼叫的this。
- bind、apply、call 方法
是綁定函式到特定的
this的方法
- new
建構式的運算子,我們之後會在原形的章節介紹到
- DOM 事件處理器
陸續會介紹到
- 箭頭函式 ES6
陸續會介紹到
this 到底有甚麼用呢?
也就是可以透過 this 指向前面的物件。
而這邊要介紹,其實物件的方法調用 (As an object method) 是最常見的形式,這邊也是要記住兩個重點:
this與函式如何宣告沒有關聯性,僅與呼叫方法有關- 物件的方法調用時,僅需要關注是在哪一個物件下呼叫
也就是說使用物件的方式調用的時候,你只需要關注它是在哪個物件下調用的就好 !
以下面的例子來說:
基本上這樣執行函式的時候,後面的函式的 this 就是指向前面這個物件。
接下來我們來看一下範例
範例 1
var myName = '真心鎮大冒險';
function callName () {
console.log(this.myName);
}
var family = {
myName: '小明家',
callName: callName
}
family.callName(); // 小明家
在這裡我們不管 callName 這個函式是怎麼定義的,我們只 care 它是在哪個物件下被呼叫。因此這個 this 現在就是指向
family 這個物件,所以很明顯透過 callName的函式印出來的結果是 '小明家'
也可以多修改一下程式碼,看看 this 現在是指向誰
var myName = '真心鎮大冒險';
function callName () {
console.log(this, this.myName);
}
var family = {
myName: '小明家',
callName: callName
}
family.callName();
範例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 這個物件,所以印出來的就會是 '小明'
範例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 會指向誰呢 ?
.
.
.
.
.
執行的結果就是 '真心鎮大冒險'
為什麼會這樣呢?
因為它被執行在全域的情況下,它的 this 就指向到了 window 的物件,所以它 console.log 出來的結果就會是 '真心鎮大冒險'