this in JavaScript in detail

English 简体中文 繁体中文 ภาษาไทย Tiếng Việt
Summary

The this keyword in JavaScript is dynamically bound, with its value determined by the function's execution context rather than its definition. In global scope or pure function calls, this typically refers to the global object, becoming undefined in strict mode, whereas a method call sets this to the invoking object. When used in a constructor, this points to the newly created instance, but within nested functions, it often defaults back to the global object, requiring workarounds. To explicitly control this in such scenarios, or within callbacks and event handlers, developers can leverage call(), apply(), or bind(). Ultimately, this consistently references the object responsible for calling the function.

คำว่า this ใน JavaScript มักจะสร้างความสับสนเสมอ และเป็นหนึ่งในกับดักที่พบบ่อยที่สุดใน JavaScript ซึ่งไม่ใช่การออกแบบที่ดีใน JavaScript (คุณสามารถอ้างอิงข้อบกพร่องในการออกแบบอื่นๆ ของ JavaScript ได้ ที่นี่) เนื่องจากคุณสมบัติ lazy binding ทำให้มันสามารถเป็น global object, current object หรือ... บางคนถึงกับหลีกเลี่ยงการใช้ this ใน JavaScript

จริงๆ แล้ว ถ้าคุณเข้าใจวิธีการทำงานของ this อย่างถ่องแท้ คุณจะรู้วิธีหลีกเลี่ยงกับดักเหล่านี้ มาดูกันว่า this ชี้ไปที่อะไรในสถานการณ์ต่อไปนี้

1. ในโค้ด global scope

alert(this)//window

this จะชี้ไปที่ global object (โดยปกติคือ window ใน web browsers) ในโค้ด global scope

2. ในการเรียกฟังก์ชันแบบ pure

function fooCoder(x) {
	this.x = x;
}
fooCoder(2);
alert(x);// Global variable x's value is 2

ในที่นี้ this ก็ชี้ไปที่ global object เช่นกัน เนื่องจากฟังก์ชันที่กำหนดไว้ใน global scope จริงๆ แล้วเป็น method หนึ่งของ global object ดังนั้น this จะเป็น global object ใน strict mode, this จะเป็น undefined

3. ในการเรียก method ของ object

var name = "clever coder";
var person = {
	name : "foocoder",
	hello : function(sth){
		console.log(this.name + " says " + sth);
	}
}
person.hello("hello world");

ผลลัพธ์จะเป็น "foocoder says hello world" this จะชี้ไปที่ person object นั่นคือ current object ที่เรียก method

4. ใน constructor

new FooCoder();

ใน constructor this จะชี้ไปที่ object ที่สร้างขึ้นใหม่ด้วย new

5. ในการเรียกฟังก์ชัน private

var name = "clever coder";
var person = {
	name : "foocoder",
	hello : function(sth){
		var sayhello = function(sth) {
			console.log(this.name + " says " + sth);
		};
		sayhello(sth);
	}
}
person.hello("hello world");//clever coder says hello world

ในฟังก์ชัน private, this ไม่ได้ binding กับ object ของ method ภายนอก แต่ binding กับ global object แทน ซึ่งถือเป็นข้อบกพร่องในการออกแบบของ JavaScript เพราะไม่มีใครต้องการให้ this ในฟังก์ชัน private ชี้ไปที่ global object ในที่นี้ วิธีแก้ปัญหาทั่วไปคือการกำหนด this ให้กับตัวแปรอื่นและอ้างอิงตัวแปรนั้นในฟังก์ชัน private

var name = "clever coder";
var person = {
	name : "foocoder",
	hello : function(sth){
		var that = this;
		var sayhello = function(sth) {
			console.log(that.name + " says " + sth);
		};
		sayhello(sth);
	}
}
person.hello("hello world");//foocoder says hello world

6. ใน call() หรือ apply()

person.hello.call(person, "world");

apply() และ call() คล้ายกัน ความแตกต่างเพียงอย่างเดียวคือ parameters ที่ส่งเข้ามาหลังจาก parameter แรก ใน apply(), parameters อื่นๆ จะถูกส่งด้วย array ในขณะที่ใน call(), parameters อื่นๆ จะถูกส่งแยกกัน

call( thisArg [,arg1,arg2,… ] );  // Parameter list,arg1,arg2,...
apply(thisArg [,argArray] );     // Parameter list,argArray

parameter แรกที่ส่งเข้ามาคือ object ที่ this จะชี้ไป เราสามารถระบุ object ใดๆ ที่จะให้ this ชี้ไปได้

7. อื่นๆ

เราอาจเห็นโค้ดด้านล่างนี้บ่อยๆ:

$("#some-ele").click = obj.handler;

ถ้าเราใช้ this ใน handler, this จะ bind กับ obj หรือไม่? เห็นได้ชัดว่าไม่ หลังจาก assignment, ฟังก์ชันจะถูกเรียกใน callback function, this จะ bind กับ $("#some-div") element นี่คือสิ่งที่เราต้องเข้าใจในที่นี้ -- execution context 

แล้วเราจะระบุ this object ให้เป็นสิ่งที่เราต้องการใน callback function ได้อย่างไร? ใน ECMAScript 5 มี method bind():

fun.bind(thisArg[, arg1[, arg2[, ...]]])

thisArg จะเป็น this object ที่เราต้องการให้เป็น

$("#some-ele").click(person.hello.bind(person));

ตอนนี้ this จะเป็น person object

ใน Prototype.js เราสามารถค้นหา implementation ของ bind() ได้:

Function.prototype.bind = function(){
  var fn = this, args = Array.prototype.slice.call(arguments), object = args.shift();
  return function(){
    return fn.apply(object,
      args.concat(Array.prototype.slice.call(arguments)));
  };
};

สรุป

1. เมื่อฟังก์ชันถูกเรียกเป็น method ของ object, this จะชี้ไปที่ object นั้น

2. เมื่ออยู่ใน pure function call, this จะเป็น global object (ใน strict mode, this จะเป็น undefined)

3. ใน constructor, this จะเป็น object ที่สร้างขึ้นใหม่

ในประโยคเดียว this จะชี้ไปที่ object ที่ฟังก์ชันถูกเรียกเสมอ

JAVASCRIPT THIS BIND GUIDE

  RELATED

  COMMENTS

0

No comment for this article.