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.

Trong JavaScript, this luôn gây nhầm lẫn, nó là một trong những cạm bẫy thường thấy nhất. this không phải là một thiết kế tốt trong JavaScript (bạn có thể tham khảo một số sai sót thiết kế khác của JavaScript tại đây), vì tính năng liên kết trễ của nó, nó có thể là một đối tượng toàn cục, đối tượng hiện tại hoặc.... Một số người thậm chí tránh sử dụng this trong JavaScript.

Thực tế, nếu bạn nắm vững cách this hoạt động, bạn sẽ biết cách tránh xa những cạm bẫy này. Hãy xem this trỏ đến đâu trong các tình huống dưới đây.

1. Trong mã phạm vi toàn cục

alert(this)//window

this sẽ trỏ đến đối tượng toàn cục (thường là window trong trình duyệt web) trong mã phạm vi toàn cục.

2. Trong một lệnh gọi hàm thuần túy

function fooCoder(x) {
	this.x = x;
}
fooCoder(2);
alert(x);// Biến toàn cục x có giá trị là 2

Ở đây, this cũng đang trỏ đến đối tượng toàn cục vì hàm được định nghĩa trong phạm vi toàn cục thực chất là một phương thức của đối tượng toàn cục. Vì vậy, this sẽ là đối tượng toàn cục. Trong chế độ nghiêm ngặt, this sẽ là undefined.

3. Trong một lệnh gọi phương thức của một đối tượng

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

Kết quả sẽ là "foocoder says hello world". this sẽ trỏ đến đối tượng person, tức là đối tượng hiện tại gọi phương thức.

4. Trong một hàm tạo

new FooCoder();

Trong một hàm tạo, this sẽ trỏ đến đối tượng mới được tạo bằng new.

5. Trong một lệnh gọi hàm riêng tư

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

Trong một hàm riêng tư, this không liên kết đối tượng của phương thức bên ngoài, thay vào đó nó liên kết với đối tượng toàn cục. Điều này được coi là một sai sót thiết kế của JavaScript vì không ai muốn this trong hàm riêng tư trỏ đến đối tượng toàn cục ở đây. Giải pháp chung là gán this cho một biến khác và tham chiếu biến đó trong hàm riêng tư.

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. Trong call() hoặc apply()

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

apply()call() tương tự nhau, sự khác biệt duy nhất là các tham số được truyền vào sau tham số đầu tiên. Trong apply(), các tham số khác sẽ được truyền bằng một mảng, trong khi trong call(), các tham số khác được truyền riêng lẻ.

call( thisArg [,arg1,arg2,… ] );  // Danh sách tham số,arg1,arg2,...
apply(thisArg [,argArray] );     // Danh sách tham số,argArray

Tham số đầu tiên được truyền vào là đối tượng mà this sẽ trỏ đến. Chúng ta có thể chỉ định bất kỳ đối tượng nào để được trỏ đến bởi this.

7. Khác

Chúng ta có thể thấy đoạn mã dưới đây thường xuyên:

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

Nếu chúng ta sử dụng this trong handler, this sẽ liên kết với obj? Rõ ràng là không, sau khi gán, các hàm được gọi trong hàm gọi lại, this sẽ liên kết với phần tử $("#some-div"). Đây là điều chúng ta cần hiểu ở đây - ngữ cảnh thực thi. 

Vậy làm cách nào để chúng ta chỉ định đối tượng this là đối tượng chúng ta muốn trong hàm gọi lại? Trong ECMAScript 5, có một phương thức bind():

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

thisArg sẽ là đối tượng this mà chúng ta muốn.

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

Bây giờ this sẽ là đối tượng person

Trong Prototype.js, chúng ta có thể tìm thấy cách triển khai của 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)));
  };
};

Kết luận

1. Khi hàm được gọi là một phương thức của một đối tượng, this sẽ trỏ đến đối tượng đó

2. Khi trong một lệnh gọi hàm thuần túy, this sẽ là đối tượng toàn cục (trong chế độ nghiêm ngặt, this sẽ là undefined)

3. Trong một hàm tạo, this sẽ là đối tượng mới được tạo

Trong một câu, this sẽ luôn trỏ đến đối tượng mà hàm được gọi trên đó.

JAVASCRIPT THIS BIND GUIDE

  RELATED

  COMMENTS

0

No comment for this article.