HomeLập trìnhJavaScriptGiải thích từ...

Giải thích từ khóa `this` của JavaScript + 5 quy tắc liên kết chính cho người mới bắt đầu học JS


JavaScript this từ khóa là một trong những khía cạnh khó nắm bắt nhất của ngôn ngữ. Nhưng nó cực kỳ quan trọng để viết mã JavaScript nâng cao hơn.

Trong JavaScript, this từ khóa cho phép chúng tôi:

  • Sử dụng lại các chức năng trong các ngữ cảnh thực thi khác nhau. Điều đó có nghĩa là, một hàm sau khi được xác định có thể được gọi cho các đối tượng khác nhau bằng cách sử dụng this từ khóa.
  • Xác định đối tượng trong ngữ cảnh thực thi hiện tại khi chúng ta gọi một phương thức.

Các this từ khóa được liên kết rất chặt chẽ với các chức năng JavaScript. Khi nó đến this, điều cơ bản là hiểu nơi một chức năng được gọi. Bởi vì chúng ta không biết những gì trong this từ khóa cho đến khi chức năng được gọi.

Việc sử dụng this có thể được phân loại thành năm khác nhau binding các khía cạnh. Trong bài viết này, chúng ta sẽ tìm hiểu về tất cả năm khía cạnh với các ví dụ.

Trong JavaScript, một Lexical Environment là nơi mã của bạn được viết về mặt vật lý. Trong ví dụ dưới đây, tên biến là lexically bên trong chức năng sayName().

function sayName() {
  let name="someName";
  console.log('The name is, ', name);
 }

Một Execution Context đề cập đến mã hiện đang chạy và mọi thứ khác giúp chạy mã đó. Có thể có rất nhiều môi trường từ vựng có sẵn nhưng môi trường từ vựng hiện nay chạy được quản lý bởi Bối cảnh thực hiện.

từ vựng
Môi trường từ điển so với bối cảnh thực thi

Mỗi Bối cảnh thực thi chứa một Environment Record. Khi công cụ JavaScript thực thi mã, các biến và tên hàm sẽ được thêm vào Bản ghi môi trường.

Hiện tượng này được gọi là Binding trong JavaScript. Binding giúp liên kết các định danh (biến, tên hàm) với this từ khóa cho một execution context.

Đừng lo lắng nếu bây giờ bạn thấy điều này hơi khó hiểu. Bạn sẽ hiểu rõ hơn khi chúng tôi tiến hành.

Ràng buộc ngầm định bao gồm hầu hết các trường hợp sử dụng để xử lý this từ khóa.

Khi chúng ta gọi một phương thức của một đối tượng, chúng ta sử dụng ký hiệu dấu chấm (.) để truy cập nó. Trong liên kết ẩn, bạn cần kiểm tra đối tượng liền kề với phương thức tại thời điểm gọi. Điều này xác định những gì this đang ràng buộc.

Hãy xem một ví dụ để hiểu nó tốt hơn.

let blog = {
    name: 'Tapas',
    address: 'freecodecamp',
    message: function() {
        console.log(`${this.name} blogs on ${this.address}`);
    }
};

blog.message();

Đây this được liên kết với đối tượng blog. Chúng tôi biết điều này bởi vì chúng tôi gọi phương thức message() trên đối tượng blog. Cho nên this.name sẽ đăng nhập tapasthis.address sẽ đăng nhập freeCodeCamp trong bảng điều khiển.

Đọc thêm  Ví dụ về chuỗi con JavaScript - Phương thức Slice, Substr và Substring trong JS

Hãy xem một ví dụ khác để hiểu rõ hơn về khái niệm này:

 function greeting(obj) {
      obj.logMessage = function() {
          console.log(`${this.name} is ${this.age} years old!`);
      }
  };

  const tom = {
      name: 'Tom',
      age: 7
  };

  const jerry = {
      name: 'jerry',
      age: 3
  };

  greeting(tom);
  greeting(jerry);

  tom.logMessage ();
  jerry.logMessage ();

Trong ví dụ này, chúng ta có hai đối tượng, tomjerry. Chúng tôi đã trang trí (nâng cao) các đối tượng này bằng cách đính kèm một phương thức gọi là logMessage().

Lưu ý rằng khi chúng ta gọi tom.logMessage()nó đã được gọi trên tom vật. Cho nên this bị ràng buộc với tom đối tượng và nó ghi lại giá trị tom7 (this.name bằng tom và this.age ở đây là 7). Điều tương tự cũng áp dụng khi jerry.logMessage() Được gọi.

Chúng ta đã thấy rằng JavaScript tạo ra một môi trường để thực thi mã mà chúng ta viết. Nó xử lý việc tạo bộ nhớ cho các biến, hàm, đối tượng, v.v. giai đoạn sáng tạo. Cuối cùng, nó thực thi mã trong Giai đoạn thực hiện. Môi trường đặc biệt này được gọi là Execution Context.

Có thể có nhiều môi trường như vậy (Bối cảnh thực thi) trong một ứng dụng JavaScript. Mỗi bối cảnh thực thi hoạt động độc lập với các bối cảnh khác.

Nhưng đôi khi, chúng ta có thể muốn sử dụng nội dung từ bối cảnh thực thi này sang bối cảnh thực thi khác. Đó là nơi ràng buộc rõ ràng phát huy tác dụng.

Trong ràng buộc rõ ràng, chúng ta có thể gọi một hàm với một đối tượng khi hàm nằm ngoài ngữ cảnh thực thi của đối tượng.

Có ba phương pháp rất đặc biệt, call(), apply()bind() giúp chúng tôi đạt được ràng buộc rõ ràng.

JavaScript như thế nào call() phương pháp hoạt động

với call() phương thức, ngữ cảnh mà hàm phải được gọi sẽ được truyền dưới dạng tham số cho call(). Hãy để chúng tôi xem cách nó hoạt động với một ví dụ:

let getName = function() {
     console.log(this.name);
 }
 
let user = {
   name: 'Tapas',
   address: 'Freecodecamp'  
 };

getName.call(user);

đây call() phương thức được gọi trên một chức năng gọi là getName(). Các getName() chức năng chỉ nhật ký this.name. Nhưng cái gì là this đây? Điều đó được xác định bởi những gì đã được chuyển đến call() phương pháp.

Đây, this sẽ liên kết với đối tượng người dùng vì chúng tôi đã chuyển người dùng làm tham số cho đối tượng call() phương pháp. Cho nên this.name nên ghi lại giá trị của thuộc tính tên của đối tượng người dùng, nghĩa là tapas.

Trong ví dụ trên, chúng ta chỉ truyền một đối số cho call(). Nhưng chúng ta cũng có thể truyền nhiều đối số cho call()như thế này:

let getName = function(hobby1, hobby2) {
     console.log(this.name + ' likes ' + hobby1 + ' , ' + hobby2);
 }

let user = {
   name: 'Tapas',
   address: 'Bangalore'  
 };

let hobbies = ['Swimming', 'Blogging'];
 
getName.call(user, hobbies[0], hobbies[1]);

Ở đây chúng tôi đã chuyển nhiều đối số cho call() phương pháp. Đối số đầu tiên phải là bối cảnh đối tượng mà hàm phải được gọi. Các tham số khác chỉ có thể là giá trị để sử dụng.

Đọc thêm  Kiểm tra JavaScript nếu không xác định – Cách kiểm tra không xác định trong JS

Ở đây tôi đang đi qua Bơi lộiViết blog như hai tham số của getName() chức năng.

Bạn có nhận thấy một điểm đau ở đây? trong trường hợp của một call(), các đối số cần phải được thông qua từng cái một – đây không phải là một cách làm việc thông minh! Đó là nơi mà phương pháp tiếp theo của chúng tôi, apply()đi vào hình ảnh.

JavaScript như thế nào apply() phương pháp hoạt động

Cách bận rộn này để truyền đối số cho call() phương pháp này có thể được giải quyết bằng một phương pháp thay thế khác được gọi là apply(). Nó hoàn toàn giống như call() nhưng cho phép bạn chuyển đối số thuận tiện hơn. Có một cái nhìn:

let getName = function(hobby1, hobby2) {
     console.log(this.name + ' likes ' + hobby1 + ' , ' + hobby2);
 }
 
let user = {
   name: 'Tapas',
   address: 'Bangalore'  
 };

let hobbies = ['Swimming', 'Blogging'];
 
getName.apply(user, hobbies);

Ở đây chúng ta có thể truyền một loạt các đối số, điều này thuận tiện hơn nhiều so với việc truyền từng đối số một.

Mẹo: Khi bạn chỉ có một đối số giá trị hoặc không có đối số giá trị nào để chuyển, hãy sử dụng call(). Khi bạn có nhiều đối số giá trị để vượt qua, hãy sử dụng apply().

JavaScript như thế nào bind() phương pháp hoạt động

Các bind() phương pháp tương tự như call() phương pháp nhưng với một sự khác biệt. không giống như call() phương thức gọi hàm trực tiếp, bind() trả về một chức năng hoàn toàn mới và thay vào đó chúng ta có thể gọi chức năng đó.

let getName = function(hobby1, hobby2) {
     console.log(this.name + ' likes ' + hobby1 + ' , ' + hobby2);
 }

let user = {
   name: 'Tapas',
   address: 'Bangalore'  
 };

let hobbies = ['Swimming', 'Blogging'];
let newFn = getName.bind(user, hobbies[0], hobbies[1]); 

newFn();

đây getName.bind() không gọi chức năng getName() trực tiếp. Nó trả về một chức năng mới, newFn và chúng ta có thể gọi nó như newFn().

Một new từ khóa được sử dụng để tạo một đối tượng từ hàm tạo.

let Cartoon = function(name, character) {
     this.name = name;
     this.character = character;
     this.log = function() {
         console.log(this.name +  ' is a ' + this.character);
     }
 };

Bạn có thể tạo các đối tượng bằng cách sử dụng new từ khóa như thế này:

 let tom = new Cartoon('Tom', 'Cat');
 let jerry = new Cartoon('Jerry', 'Mouse');

Khi một chức năng được gọi với new từ khóa, JavaScript tạo nội bộ this object(like, this = {}) trong hàm. Mới được tạo this liên kết với đối tượng được tạo bằng cách sử dụng new từ khóa.

Nghe có vẻ phức tạp? Ok, hãy chia nhỏ nó ra. Lấy dòng này,

let tom = new Cartoon('Tom', 'Cat');

Ở đây, hàm Cartoon được gọi với new từ khóa. Vì vậy, nội bộ tạo ra this sẽ được liên kết với đối tượng mới được tạo ở đây, đó là tom.

Bạn nghĩ gì sẽ là đầu ra của mã dưới đây? Là gì this ràng buộc ở đây?

let sayName = function(name) {
    console.log(this.name);
};

window.name="Tapas";
sayName();

Nếu this từ khóa không được giải quyết với bất kỳ ràng buộc nào, implicit, explicit hoặc newsau đó this bị ràng buộc với window(global) vật.

Đọc thêm  JavaScript 函数式编程入门指南

Có một ngoại lệ mặc dù. JavaScript chế độ nghiêm ngặt không cho phép ràng buộc mặc định này.

"use strict";
function myFunction() {
  return this;
}

Trong trường hợp trên, thisundefined.

Trong trình xử lý sự kiện HTML, this liên kết với các phần tử HTML nhận sự kiện.

<button onclick="console.log(this)">Click Me!</button>

Đây là nhật ký đầu ra trong bảng điều khiển khi bạn nhấp vào nút:

"<button onclick='console.log(this)'>Click Me!</button>"

Bạn có thể thay đổi kiểu nút bằng cách sử dụng this từ khóa, như thế này:

<button onclick="this.style.color="teal"">Click Me!</button>

Nhưng hãy chú ý khi bạn gọi một chức năng trên nút bấm và sử dụng this bên trong chức năng đó.

<button onclick="changeColor()">Click Me!</button>

và JavaScript:

function changeColor() {
  this.style.color="teal";
}

Đoạn mã trên sẽ không hoạt động như mong đợi. Như chúng ta đã thấy trong Quy tắc 4, ở đây this sẽ bị ràng buộc với đối tượng toàn cầu (ở chế độ ‘không nghiêm ngặt’) khi không có Phong cách đối tượng để thiết lập màu sắc.

Để tóm tắt,

  • Trong trường hợp ràng buộc ngầm, this liên kết với đối tượng liền kề với toán tử dấu chấm (.) trong khi gọi phương thức.
  • Trong trường hợp ràng buộc rõ ràng, chúng ta có thể gọi một hàm với một đối tượng khi hàm nằm ngoài ngữ cảnh thực thi của đối tượng. Các phương pháp call(), apply()bind() đóng một vai trò lớn ở đây.
  • Khi một chức năng được gọi với new từ khóa, các this từ khóa bên trong hàm liên kết với đối tượng mới đang được xây dựng.
  • Khi mà this từ khóa không được giải quyết với bất kỳ ràng buộc nào, implicit, explicit hoặc newsau đó this bị ràng buộc với window(global) vật. Trong chế độ nghiêm ngặt của JavaScript, this sẽ không được xác định.
  • Trong trình xử lý sự kiện HTML, this liên kết với các phần tử HTML nhận sự kiện.

Còn một trường hợp nữa là this cư xử khác nhau, chẳng hạn như với ES6 arrow functionS. Chúng tôi sẽ xem xét điều đó trong một bài viết trong tương lai.

Tôi hy vọng bạn tìm thấy bài viết này sâu sắc. Bạn cũng có thể thích,

Nếu bài viết này hữu ích, hãy chia sẻ nó để những người khác cũng có thể đọc nó. Bạn có thể @ tôi trên Twitter (@tapasadhikary) với các bình luận, hoặc thoải mái theo dõi tôi.





Zik.vn – Biên dịch & Biên soạn Lại

spot_img

Create a website from scratch

Just drag and drop elements in a page to get started with Newspaper Theme.

Buy Now ⟶

Bài viết liên quang

DMCA.com Protection Status