Từ khóa “This” trong JavaScript – Cách đưa “This” vào trong Lexical-Scope thay vì Dynamic-Scope

Trong JavaScript, execution context là môi trường mà một hàm thực thi trong đó. Tất cả các execution context đều có giai đoạn tạo và giai đoạn thực thi. Trong giai đoạn tạo, nó tạo ra ràng buộc với đối tượng this.

This trong JavaScript là một đối tượng mà có thuộc tính là các hàm.”

Để hiểu rõ hơn, chúng ta hãy cùng xem dòng lệnh dưới đây:

const person = {
name: "John",
speak() {
return "I am " + this.name;
}
}person.speak()

Từ dòng lệnh trên, bạn nghĩ đâu là giá trị của this? Đối tượng person có thuộc tính là hàm speak() chính là giá trị của this. Đoạn code trên sẽ trả về chuỗi “I am John”.

Có hai lý do khiến this trở lên hữu ích cho các JavaScript developer:

1. Nó cung cấp một phương thức có quyền truy cập vào đối tượng của nó để nó có thể sử dụng các thuộc tính và phương thức của đối tượng như chúng ta đã thấy trong ví dụ trên.

2. Nó giúp thực thi cùng một mã cho nhiều đối tượng mà không cần phải viết lại mã. Để hiểu điều này, hãy xem ví dụ dưới đây:

const name = "Tim"
function getName() {

return this.name;

}
const object1 = {

name: "Mark",

getName: getName

}
const object2 = {

name: "Sundar",

getName: getName

}
console.log(getName())

console.log(object1.getName())

console.log(object2.getName())

Sau khi chạy, chương trình trả về:

Tim
Mark
Sundar

Bạn có nhận thấy giá trị của this thay đổi như thế nào dựa trên đối tượng gọi hàm không?

Lexical scope sử dụng vị trí mà một biến hoặc hàm được khai báo trong mã nguồn để xác định biến, hàm nào có sẵn cho nó. Ví dụ, trong đoạn mã dưới đây, example() sẽ có quyền truy cập vào biến superName vì nó được khai báo bên trong hàm super(). Hàm example() được gọi từ đâu không quan trọng. Điều đó sẽ không thay đổi quyền truy cập của nó vào biến superName.

function super() {
var superName = "Mario"
function example() {
console.log(superName)
}
}

Ngược lại, dynamic scoping quan tâm đến vị trí và cách thức một hàm được gọi để xác định những biến nào có sẵn cho nó.

Trong JavaScript, mọi thứ đều là lexical scope ngoại trừ this là dynamic scope và nó có thể gây khó hiểu cho mã. Để hiểu điều này, chúng ta hãy xem ví dụ dưới đây:

const person = {

name: 'Billy',

speak() {

console.log('a', this)

var anotherSpeak = function() {

console.log('b', this)
}
anotherSpeak()
}
}person.speak()

Bạn sẽ mong đợi cả hai console log đều in ra cùng một giá trị this. Tuy nhiên, các hàm speak() và anotherSpeak() được gọi ở những nơi khác nhau. Điều này ảnh hưởng đến giá trị của this.

Để tránh điều này, có hai cách mà chúng ta có thể đưa this vào lexical scope:

1. Arrow function

const person = {

name: 'Billy',

speak() {

console.log('a', this)

var anotherSpeak = () => {

console.log('b', this)
}
anotherSpeak()
}
}person.speak()

2. Bind function- trước khi có arrow function, phương pháp này được sử dụng để tạo một hàm ràng buộc lexical. Hãy thử sử dụng bind function trong ví dụ trên:

const person = {
name: 'Billy',
speak() {
console.log('a', this)

var anotherSpeak = function() {

console.log('b', this)
}
return anotherSpeak.bind(this)
}
}person.speak()()

Kết quả trả về như khi sử dụng arrow function. Tuy nhiên, các bạn nên sử dụng arrow function thay vì bind function vì nó rõ ràng hơn và gần đây đã được thêm vào ES6.

TÁC GIẢ: ANUSHREE SINGH