Skip to content

Latest commit

 

History

History
204 lines (151 loc) · 4.97 KB

06.md

File metadata and controls

204 lines (151 loc) · 4.97 KB

Javascript What is "this" ?

this 是 Javascript 的一個關鍵字。隨著使用場合不同,this 的值也會產生變化。但原則上就是:

this 指的是,調用函數的那個對象。

以下分成五種常見的狀況來探討:


1. this 指向於調用該函式之物件

在 C# 裡,一個物件內的成員函式裡的 this 指的即是該成員函式所在之物件,但在 Javascript 裡的 this 看的是是誰調用該函式,而不是看該函式被定義在哪個物件內。

公式:

物件.函式(); //函式內的 this 指向該物件

舉例:

var obj = {
	x: 20,
	f: function(){ console.log(this.x); } //20
};

obj.f(); //由於調用 f 函式時,點前面物件為 obj,故 f 內的 this 指向 obj,則輸出為 20。

obj.innerobj = {
	x: 30,
	f: function() { console.log(this.x); } //30
}

obj.innerobj.f(); //由於調用 f 函式時,點前面物件為 obj.innerobj,故 f 內的 this 指向 obj.innerobj,則輸出為 30。

2. this 指向全域物件

如果調用函式的前方並未有物件,則函式內 this 就指向全域物件。

  • 瀏覽器內全域物件為 window 物件。
  • node.js 中全域物件則為 GLOBAL 物件。

公式:

函式(); //函式內的 this 指向全域物件

舉例:

var x = 10;
var f = function() {
	console.log(this.x); //10
};

f(); //由於調用 f 函式時,前方並未有[物件.]的形式,故 f 內的 this 指向全域物件,則輸出全域變數的 10。

3. this 指向利用 call 或 apply 所指派給 this 的物件

call 與 apply 都是呼叫該函式並讓該函式的 this 指向給予 call 或 apply 的第一個參數。 至於call 和 apply 的差別則是在於其後面給予被調用之函式的參數放入的方法不同,一個是直接攤平放在第二個以後的參數;一個是直接放入一個裡面放要給予之參數的陣列。

公式:

(A物件.)函式.call(B物件, 參數1, 參數2, ...); //函式的 this 指向 B 物件 (若 B 物件為 null,則指向全域物件) (A物件.)函式.apply(B物件, [參數1, 參數2, ...]); //函式的 this 指向 B 物件 (若 B 物件為 null,則指向全域物件)

舉例 1. call 時有帶入參數:

var obj1 = {
	x: 20,
	f: function(){ console.log(this.x); } //30
};

var obj2 = {
	x: 30
};

obj1.f.call(obj2); //利用 call 指派 f 的 this 為指向 obj2,故輸出為 30

舉例 2. call 時無帶入參數:

var x = 10;

var obj1 = {
	x: 20,
	f: function(){ console.log(this.x); } //10
};

var obj2 = {
	x: 30
};

obj1.f.call(); //利用 call 指派 f 的 this 為指向 obj2,故輸出為 10

4. this 指向 new 所產生之新物件

若將函式當作建構式 (constructor) 來用,則內部的 this 則指向於 new 所產生之新物件。

公式:

new 建構式(); //建構式內之 this 指向 new 所產生之新物件

舉例:

var x = 2;

function test() {
    this.x = 1;
}

var o = new test();
alert(o.x); //1
alert(x); //2

5. callback 函式內的 this 會指向於調用放入該 callback 的函式之 this 所指向之物件

先想想在 jQuery 中,若要讓 #button 這個元素被 click 的時候,內容改為 “Clicked” 這樣的字串,程式碼如下:

$("#button").click(function(){
	this.html("Clicked");
})

此時這個 this 就是指向 $("#button") 這個物件。這樣的方式在網頁上確實很常見到。


常見誤導範例

範例 1. 物件之成員函式內有函式:

var x = 10;
var obj = {
	x: 20,
	f: function(){
		console.log(this.x);
		var foo = function(){ console.log(this.x); }
		foo(); // (2)
	}
};

obj.f();  // (1)
//Ans: 20 10
  • (1): obj.f() 調用時,f 前面物件為 obj,故 f 內的 this 指向 obj。
  • (2):調用 foo() 時,調用的前方並未有物件,故 foo 內的 this 指向全域物件,所以輸出會是全域變數的 x 的值。

若要讓 foo 內使用 obj.x 的值,解法如下:

var x = 10;
var obj = {
	x: 20,
	f: function(){
		console.log(this.x);
		var that = this; //使用 that 保留在這個函式內的 this
        var foo = function(){ console.log(that.x); } //使用 that 取得 obj
		foo();
	}
};

obj.f();
//Ans: 20 20

範例 2. 借用函式:

var x = 10;

var obj = {
	x: 20,
	f: function(){ console.log(this.x); }
};

obj.f(); // (1)

var fOut = obj.f;
fOut(); //(2)

var obj2 = {
	x: 30,
	f: obj.f
}

obj2.f(); // (3)
//Ans: 20 10 30
  • (1):調用 obj.f() 時,此時 this 指到 obj,所以輸出為 20。
  • (2):調用 fOut() 時,因為 fOut() 前面沒有任何物件,所以指向全域物件,故輸出為 10。
  • (3):調用 obj2.f() 時,因為調用者為 obj2,故輸出為 30。

Reference

  1. https://software.intel.com/zh-cn/blogs/2013/10/09/javascript-this
  2. http://www.ruanyifeng.com/blog/2010/04/using_this_keyword_in_javascript.html

tags: Javascript this context