Hãy cùng tìm hiểu về từ khóa this trong javascript với Thế giới JS,, nó luôn giữ tham chiếu đến một đối tượng duy nhất, xác định ngữ cảnh thực thi của dòng code hiện tại. Hàm, trong JavaScript, về cơ bản là các đối tượng. Giống như các đối tượng, chúng có thể được gán cho các biến, được truyền cho các hàm khác và được trả về từ các hàm. Và giống như các đối tượng, chúng có thuộc tính riêng của chúng. Một trong những thuộc tính này là this.
Giá trị mà trình biên dịch này lưu trữ là ngữ cảnh thực thi hiện tại của chương trình JavaScript. Do đó, khi được sử dụng bên trong một hàm, giá trị này sẽ thay đổi tùy thuộc vào cách hàm đó được định nghĩa, cách nó được gọi và bối cảnh thực thi mặc định. từ khóa this sẽ đề cập đến các đối tượng khác nhau tùy thuộc vào cách nó được sử dụng.
Hàm, trong JavaScript, có thể được gọi theo nhiều cách:
1.this với lời gọi hàm:
Gọi hàm đề cập đến quá trình gọi một hàm sử dụng tên của nó hoặc một biểu thức đánh giá đối tượng hàm, theo sau là một tập hợp các dấu ngoặc mở và đóng đầu tiên (việc bao gồm các dấu ngoặc cho biết rằng chúng tôi đang yêu cầu công cụ JavaScript thực thi hàm ngay lập tức ).
Ví dụ:
// https://vpsus.vn/ // https://www.facebook.com/groups/893052378563701 // https://twitter.com/thegioijs function doSomething() { // do something here } // function invocation doSomething();
this bên trong hàm doSomething, nếu nó được gọi thông qua lời gọi hàm như trên, có giá trị của đối tượng toàn cục, là đối tượng window trong môi trường trình duyệt:
// https://vpsus.vn/ // https://www.facebook.com/groups/893052378563701 // https://twitter.com/thegioijs function doSomething(a, b) { // adds a propone property to the Window object this.propone = "test value"; } // function invocation doSomething(); document.write(window.propone);
Đầu ra:
test value
Tuy nhiên, đây không phải là luôn luôn như vậy. Nếu hàm doSomething() đang chạy ở chế độ nghiêm ngặt , nó sẽ ghi log là không xác định(undefined) thay vì đối tượng cửa sổ. this là do, ở chế độ nghiêm ngặt (được biểu thị bằng dòng: ‘usestrict’; ), giá trị mặc định của giá trị này, đối với bất kỳ đối tượng hàm nào, được đặt thành không xác định(undefined) thay vì đối tượng chung.
Ví dụ :
// https://vpsus.vn/ // https://www.facebook.com/groups/893052378563701 // https://twitter.com/thegioijs function doSomething() { // enable the strict mode 'use strict'; // logs undefined document.write(this + '<br>') function innerFunction() { // Also logs undefined, indicating that // strict mode permeates to inner function scopes document.write(this) } innerFunction(); } // function invocation doSomething();
Đầu ra:
undefined
undefined
2.this với lời gọi phương thức:
Hàm, khi được định nghĩa là trường hoặc thuộc tính của đối tượng, được gọi là phương thức.
// https://vpsus.vn/ // https://www.facebook.com/groups/893052378563701 // https://twitter.com/thegioijs let person = { name : "John", age : 31, logInfo : function() { document.write(this.name + " is " + this.age + " years old "); } } // logs John is 31 years old person.logInfo()
Đầu ra:
John is 31 years old
Trong ví dụ code trên, logInfo() là một phương thức của đối tượng person và chúng tôi đã gọi nó bằng cách sử dụng mẫu gọi đối tượng. Nghĩa là, chúng tôi đã sử dụng các trình truy cập thuộc tính để truy cập phương thức là một phần của đối tượng.
Một lời gọi như vậy yêu cầu sử dụng một biểu thức đánh giá đối tượng mà phương thức của chúng ta là một phần và một bộ truy cập thuộc tính (Ví dụ: person.logInfo() ) theo sau là một tập hợp các dấu ngoặc đơn mở và đóng. Điều cần thiết là phải hiểu cách hoạt động của các lời gọi và các lời gọi phương thức khác nhau.
Đến lượt nó, this sẽ giúp chúng ta hiểu ngữ cảnh này có thể là gì trong bất kỳ chức năng cụ thể nào bởi vì, trong mỗi lời gọi này, giá trị của this là khác nhau.
Bên trong một phương thức như vậy, đã được gọi bằng cách sử dụng bộ truy cập thuộc tính, this sẽ có giá trị của đối tượng đang gọi, nghĩa là this sẽ trỏ đến đối tượng được sử dụng cùng với bộ truy cập thuộc tính để thực hiện cuộc gọi.
Ví dụ :
// https://vpsus.vn/ // https://www.facebook.com/groups/893052378563701 // https://twitter.com/thegioijs let add = { num : 0, calc : function() { // logs the add object document.write(this + ' ') this.num += 1; return this.num; } }; // logs 1 document.write(add.calc() + '<br>'); // logs 2 document.write(add.calc());
Đầu ra:
[object Object] 1
[object Object] 2
Trong ví dụ trên, calc() là một phương thức của đối tượng bổ sung và do đó được gọi bằng cách sử dụng quy tắc gọi phương thức ở dòng 9 và 10.
Và chúng ta biết, khi các mẫu gọi phương thức được sử dụng, giá trị của this được đặt thành lệnh gọi sự vật. Bên trong phương thức calc() này, giá trị của this được đặt thành đối tượng gọi, trong trường hợp của chúng ta, đối tượng này được thêm vào. và do đó chúng ta có thể truy cập thành công thuộc tính num của add.
Tuy nhiên, bây giờ chúng ta hãy xem xét một điểm khó hiểu chính: Điều gì xảy ra với this trong một hàm được lồng bên trong một phương thức của một đối tượng?
// https://vpsus.vn/ // https://www.facebook.com/groups/893052378563701 // https://twitter.com/thegioijs let add = { num : 0, calc : function() { // logs the add object document.write(this + ' ') function innerfunc() { this.num += 1; // logs the window object document.write(this + ' '); return this.num } return innerfunc(); } }; // logs NaN document.write(add.calc() + '<br>'); // logs NaN document.write(add.calc());
Đầu ra:
[object Object] [object Window] NaN
[object Object] [object Window] NaN
Hãy cố gắng hiểu những gì vừa xảy ra. Khi chúng ta gọi calc() ở dòng 14 và 15, chúng ta đang sử dụng lời gọi phương thức để thiết lập this để thêm vào calc(). this có thể được xác minh bằng cách sử dụng câu lệnh log ở dòng 4.
Tuy nhiên, innerfunc() được gọi từ bên trong phương thức calc() bằng cách sử dụng một lời gọi hàm đơn giản (dòng 11). this có nghĩa là, bên trong innerfunc(), đối tượng này được đặt thành đối tượng chung, không có thuộc tính num và do đó thu được kết quả đầu ra NaN.
Làm thế nào để chúng tôi giải quyết vấn đề này? Làm thế nào chúng ta có thể giữ lại giá trị của this từ phương thức bên ngoài bên trong hàm lồng nhau?
Một giải pháp là gán giá trị this từ hàm bên ngoài cho một biến được sử dụng trong hàm lồng nhau như sau:
// https://vpsus.vn/ // https://www.facebook.com/groups/893052378563701 // https://twitter.com/thegioijs let add = { num : 0, calc : function() { // logs the add object document.write(this + ' ') // using thisreference variable to // store the value of this thisreference = this; function innerfunc() { // using the variable to access the // context of the outer function thisreference.num += 1; // logs the add object document.write(thisreference + ' '); return thisreference.num; } return innerfunc(); } }; // logs 1 document.write(add.calc() + '<br>'); // logs 2 document.write(add.calc());
Đầu ra:
[object Object] [object Object] 1
[object Object] [object Object] 2
Các giải pháp khác cho vấn đề này liên quan đến việc sử dụng bind(), call() hoặc apply() mà chúng tôi sẽ sớm xem xét.
3.this với lời gọi hàm tạo:
Lời gọi hàm tạo được thực hiện khi một từ khóa mới được theo sau bởi một tên hàm và một tập hợp các dấu ngoặc đơn mở và đóng (có hoặc không có đối số).
Ví dụ: let person1= new People(‘John’, 21);
Ở đây, person1 là đối tượng mới được tạo và People là hàm tạo được sử dụng để tạo đối tượng này. Lời gọi hàm tạo là một trong một số cách tạo đối tượng trong JavaScript. Chính xác thì điều gì sẽ xảy ra khi chúng ta sử dụng từ khóa mới kết hợp với tên hàm? – Về cơ bản có năm bước liên quan đến việc tạo một đối tượng thông qua phương pháp này.
Hãy để chúng tôi nghiên cứu chúng với ví dụ sau:
// https://vpsus.vn/ // https://www.facebook.com/groups/893052378563701 // https://twitter.com/thegioijs let people = function(name, age) { this.name = name; this.age = age; this.displayInfo = function() { document.write(this.name + " is " + this.age + " years old"); } } let person1 = new people('John', 21); // logs John is 21 years old person1.displayInfo();
Đầu ra:
John is 21 years old
- Đầu tiên, một đối tượng trống được tạo là một thể hiện của tên hàm được sử dụng với new(tức là: people(name, age)). Nói cách khác, nó đặt thuộc tính hàm tạo của đối tượng thành hàm được sử dụng trong lời gọi (people(name, age)).
- Sau đó, nó liên kết nguyên mẫu của hàm tạo (people) với đối tượng mới được tạo, do đó đảm bảo rằng đối tượng này có thể kế thừa tất cả các thuộc tính và phương thức của hàm tạo
- Sau đó, hàm khởi tạo được gọi trên đối tượng mới tạo này. Nếu nhớ lại lời gọi phương thức, chúng ta sẽ thấy điều đó cũng tương tự. Như vậy, bên trong hàm tạo, this nhận giá trị của đối tượng mới tạo được sử dụng trong lời gọi.
- Cuối cùng, đối tượng đã tạo, với tất cả các thuộc tính và phương thức được đặt, được trả về person1
Trình duyệt được hỗ trợ:
- Google Chrome
- Microsoft Edge
- Firefox
- Opera
- Safari
Tiếp theo, hãy cùng Thế giới JS tìm hiểu thêm các kiến thức về Javascript trong các bài tiếp theo trong series học miễn phí Javascript từ cơ bản tới nâng cao.
Nếu bạn cảm thấy hữu ích và yêu thích Thế giới JS, hãy tham gia và theo dõi chúng tôi để nhận thêm nhiều kiến thức MIỄN PHÍ hơn nữa nhé:
Share to learn more than!
Share to learn more than!