this是什麼,取決於被呼叫的呼叫地點。
昨天有提到說,呼叫函式時候會傳遞隱含參數: arguments 和 this 並講解了 arguments ,今天我們就來探討 this 吧!
我們都會呼叫函式來使用,但有想過到底是從哪裡呼叫到這個函式嗎?
this 通常被稱作函式背景空間( function context),也就是說透過 this 我們可以知道到底是由誰呼叫這支函式。我們無法在一開始定義它,只有函式呼叫時候才能確定。
函式的呼叫有四種方式:
apply
、call
呼叫apply
、call
我們會在下一篇中介紹,我們今天主要介紹上述三種呼叫方式。
function funA(){
console.log(this);
}
funA();//Window
由於是在全域環境呼叫 funA
,所以這時候的 this
就會是 window
。
所以很多剛學習的人都會遇到這個問題:
function funA(){
this.count ++;
}
funA.count = 0;
funA();
console.log(funA.count);//0
明明已經宣告 funA.count = 0
怎麼會沒有加到呢?這就是因為 funA
是被全域環境也就是 window
呼叫,所以 this
並不是你預期的 funA
。
那到底加了誰的 count
呢? 你可以嘗試印出 window.count
會發現是 NaN
,是因為你賦予 window
一個 count
屬性且一開始沒有給定初始值,
所以會變成 undefined+ 1 = NaN
。
或許你認為這樣就可以解決問題:
function funA(val){
val.count ++;
}
var dart = {
count:0
};
funA(dart);
console.log(dart.count);//1
但這樣你只是在逃避 this
這個問題而已!!
要透過 this
解決方案有兩種,一個是等下提到的作為物件的方法;一個是明天會說的 call
及 apply
。
函式可以透過寫在物件裡面去呼叫,這個呼叫方式稱作作為方法(method),相信大家都知道,但你知道在這時候的 this
是什麼嗎?
var obj = {
funA:function(){
console.log(this);
console.log(this===obj);
}
}
obj.funA();
//{funA: ƒ}
//true
可以看到這時候的 this
是 obj
物件,也是是說我們是透過 obj
去呼叫的。
但是要注意一個小地方:
function funA(){
console.log(this);
console.log(this===obj);
}
var obj = {
a:funA
}
funA();
//Window
//false
雖然你認為我已經讓 obj
參照 funA
了,但是當你直接執行 funA
時,還是由全域環境去呼叫,這也呼應了我們開頭所說的「我們無法在一開始定義它,只有函式呼叫時候才能確定」。
我們可以利用作為方法呼叫來解決作為函式呼叫的問題:
function funA(){
this.count ++;
}
var obj = {
count : 0,
sum : funA
};
obj.sum();
console.log(obj.count);//1
建構式的函式宣告就跟任何函式一樣,也可以用宣告和表達來建立新物件。
要作為建構式函式來呼叫函式,必須要在函式呼叫前加上 new
:
function myConstructor(){
this.count = 0 ;
this.sum = function(){
return this.count ++
}
}
var a = new myConstructor();
a.sum();
console.log(a.count);
也許有人會覺得,這跟作為方法呼叫很像,那用物件去寫就好何必這麼麻煩還要學建構式,用奇怪的 new
去呼叫函式。
這邊就來說明一下,使用 new
呼叫函式時,會發生什麼事:
如果我們今天需要兩個相同的物件,如果用作為物件方法呼叫的話就必須建立兩個不同的物件,否則會參照到同樣的物件並修改。
但是建構式就不需要,因為每一個都是一個新的物件:
function myConstructor(){
this.count = 0 ;
this.sum = function(){
return this.count ++
}
}
var a = new myConstructor();
var b = new myConstructor();
a.sum();
console.log(b.count); //0
以上就是 this 的基本三種呼叫方式,若有錯誤及參考資料未附上勞請留言。
明天我們會介紹 this 的稍微進階應用 call
及apply
。
參考資料:
忍者 JavaScript 開發技巧探秘
你所不知道的JS - this
彻底理解js中this的指向,不必硬背。