Javascript 中的 this
Javascript this 一直都是面試問題的必考題之一,為了怕自己忘記還是先來記錄一下。
首先要知道的第一件事,在 javascript 中 this 的值是動態的,未指定的 this 都會指向全域。為什麼會這樣呢?先來看看 MDN 是如何定義 this:
In most cases, the value of
this
is determined by how a function is called (runtime binding). It can't be set by assignment during execution, and it may be different each time the function is called.
說明 this 的值是隨著被呼叫的方式而帶出不同的內容,換句話說,除了在未指定this指向全域外,this的內容還受函式的宣告方法影響,要搞清楚這裡就要介紹this的調用方式。
物件的方法調用 (As an object method)
我們稱在物件中新增的function為method,如果是呼叫物件中的method,method中的this會指向物件,這就是以物件方法調用,但是如果是直接呼叫物件中method,this則會指向window,以MDN對this的定義來說,this會因為function的呼叫方式而有所同,代表this的值其實是由被呼叫的方式來決定的而非以函式宣告的方式。
function callName() {
console.log(this.title)
}var title = "I am object 1"
var object_2 = {
title: "I am object 2",
name: callName
}object_2.name()//I am object 2
callName()//I am object 1
建構式的調用 (As a constructor)
講到this就一定要從物件導向開始談,在 javascript 中所有的資料都屬於object,缺少將所有資料聯繫起來的一種方式,所以就有了原型練(prototype chain)的出現。
new
在建構式下new會建立一個空物件,並且this會指向該物件,用以下範例解釋:
function DOG(name){this.name = namethis.species = '犬科'}var dogA = new DOG('大毛')console.log(dogA.name)//大毛
當我們使用new這個關鍵字的時候,過程中依序發生了這些事:
1. 建立一個空物件
2. 執行 DOG 函式
3. DOG 函式裡的 this 被指定成剛剛的空物件
call 與 apply 調用
apply和call的功能是改變 this 的值,套用後this就是就是指傳入的第一個參數。
function addFunc(a,b){
console.log(a + b)
}function apply_add() {return addFunc.apply(this, arguments);}
apply_add(1,2); // 3function call_add() {return addFunc.call(this, ...arguments);}
call_add(3,4); // 7
bind 調用
bind 跟 call、apply 不同的是,bind 綁定了 this 之後會建立一個新函式,不會回傳函式結果並且 this 是無法改變的。
function addFunc(...args){ let result = 0 args.map((arg) => result = result + arg) console.log(this, result)}var add1 = addFunc.bind("total",1,2);var add_new = add1.bind("newt_value",2,3);add1(2,3)//total 8add_new(3,4)//total 15
總結
- 在未指定this的狀況下,this都會指向全域。
- this的值是以被呼叫的方式來決定。
- call、apply、bind差異
call
語法:fn.call(this, arg1, arg2…, argn)
跟別的物件借用函式,必須逐項傳入
apply
語法:fn.apply(this, [arg1, arg2…, argn]
跟別的物件借用函式,接受傳入參數為陣列
bind
語法:fn.bind(this, arg1, arg2…, argn)
借用已建立的函式來創造新的函式,但將 `this` 綁到指定的物件上
參考資料
一次搞懂前端面試最愛問的 apply、bind、call
JavaScript 的 this 到底是誰?
談談 JavaScript 中的 “this” 和它的問題
this
What’s THIS in JavaScript ?
Javascript继承机制的设计思想
函數原型最實用的 3 個方法 — call、apply、bind