SydexaSydexa
Trang chủKhoá họcBài viết
Khi "this" Không Phải Là Thứ Bạn Nghĩ: Cuộc Phiêu Lưu Của Một React Developer
Frontend

Khi "this" Không Phải Là Thứ Bạn Nghĩ: Cuộc Phiêu Lưu Của Một React Developer

Nguyen Anh Tuan
|
27/08/2025
|
4 phút đọc

Câu chuyện bắt đầu từ một bug kỳ lạ...

Hãy tưởng tượng: 3 giờ sáng, anh em vẫn ngồi trước màn hình. Component React của anh em hoạt động hoàn hảo... cho đến khi anh em truyền một method vào props. Đột nhiên, this.setState ném ra lỗi "Cannot read property 'setState' of undefined".

Nghe có quen không 😆

Nếu anh em đã từng trải qua cảm giác này, chúc mừng - anh em vừa va phải một trong những bí ẩn thú vị nhất của JavaScript: con trỏ this.

Câu chuyện về một cửa hàng cà phê JavaScript

Hãy quên React đi một chút. Tôi muốn kể cho bạn nghe về một quán cà phê đặc biệt trong thế giới JavaScript:

const coffeeMachine = {
  brand: "EspressoMaster 3000",
  temperature: 95,
  brew() {
    console.log(`${this.brand} đang pha cà phê ở ${this.temperature}°C`);
  }
};

coffeeMachine.brew(); // "EspressoMaster 3000 đang pha cà phê ở 95°C" ✅

Màn hình in ra "EspressoMaster 3000 đang pha cà phê ở 95°C" ✅

Mọi thứ vẫn hoàn hảo. Máy pha cà phê hoạt động, cuộc sống tươi đẹp.

Nhưng khoan đã, nếu như làm như sau:

const justBrew = coffeeMachine.brew;
justBrew(); // "undefined đang pha cà phê ở undefined°C" 🤯

Plot twist! Máy pha cà phê đã... mất trí nhớ? Chuyện gì đã xảy ra?

Sự thật: Functions là những người làm thuê

Đây là điều mà nhiều developer không nhận ra: Trong JavaScript, methods chỉ là functions được lưu trong objects. Chúng không "thuộc về" object đó theo cách bạn tưởng.

Hãy tưởng tượng functions như những người làm thuê. Khi anh em viết:

const coffeeMachine = {
  brand: "EspressoMaster 3000",
  brew() {
    console.log(`${this.brand} đang pha cà phê`);
  }
};

JavaScript thực sự lưu trữ nó như thế này:

// brew thực chất chỉ là một người làm thuê "tự do"
function brew() {
  console.log(`${this.brand} đang pha cà phê`);
}

// Được "thuê" bởi coffeeMachine
coffeeMachine.brew = brew;

"this" - Chiếc áo đồng phục của cửa hàng

Bí mật nằm ở đây: this giống như chiếc áo đồng phục mà người làm thuê mặc - nó thay đổi tùy theo quán cà phê họ đang làm việc.

Khi bạn gọi coffeeMachine.brew(), JavaScript âm thầm làm điều này:

// Đằng sau hậu trường
function callMethod(shop, methodName) {
  const barista = shop[methodName];  // Tìm người làm thuê (function)
  barista.call(shop);                 // Mặc áo đồng phục của shop này
}

// coffeeMachine.brew() tương đương với:
callMethod(coffeeMachine, "brew");

Nhưng khi bạn làm:

const justBrew = coffeeMachine.brew;
justBrew(); // Người làm thuê không biết mình đang làm ở đâu!

Không có quán cà phê nào → Người làm thuê không có áo đồng phục → this = undefined (hoặc window).

Một Người làm tại nhiều quán cà phê?

Lúc đầu, điều này có vẻ như một lỗi thiết kế. Nhưng không! Đây là sức mạnh thực sự:

const italianCafe = {
  brand: "Italiano Express",
  temperature: 92
};

const vietnameseCafe = {
  brand: "Sài Gòn Drip",
  temperature: 85
};

function brew() {
  console.log(`${this.brand} pha cà phê ở ${this.temperature}°C`);
}

// Một người làm thuê, làm việc ở nhiều quán!
brew.call(italianCafe);     // "Italiano Express pha cà phê ở 92°C"
brew.call(vietnameseCafe);   // "Sài Gòn Drip pha cà phê ở 85°C"

Người làm thuê có thể làm việc ở bất kỳ quán nào, mặc áo đồng phục của quán đó. Điều này cho phép JavaScript có những patterns cực kỳ linh hoạt như mixins, decorators, và method borrowing.

Quay lại với React: Bây giờ mọi thứ đã sáng tỏ

Anh em nhớ bug React lúc đầu không? Giờ chắc đã hiểu tại sao:

class CoffeeShopApp extends React.Component {
  constructor() {
    super();
    this.state = { cupsServed: 0 };
  }

  serveCoffee() {
    // 'this' ở đây là ai?
    this.setState({ cupsServed: this.state.cupsServed + 1 });
  }

  render() {
    return (
      // Khi truyền như prop, serveCoffee mất "áo đồng phục"!
      <button onClick={this.serveCoffee}>
        Serve Coffee
      </button>
    );
  }
}

Một số solutions cho vấn đề đó như sau:

Solution 1: Arrow function (tự động giữ áo đồng phục)


serveCoffee = () => {
  this.setState({ cupsServed: this.state.cupsServed + 1 });
}

Solution 2: Bind - "khâu" áo đồng phục vào nhân viên


<button onClick={this.serveCoffee.bind(this)}>

Solution 3: Wrapper - gọi người làm thuê qua quản lý

<button onClick={() => this.serveCoffee()}>

Bài học từ quán cà phê JavaScript

this trong JavaScript không phải là bug - nó là một tính năng cực kỳ hay ho. Một khi bạn hiểu rằng:

  1. Functions là người làm thuê - Họ không gắn chặt với một "công ty" nào
  2. Context là chiếc áo đồng phục - Được mặc khi làm việc, không phải khi ký hợp đồng
  3. Bạn là ông chủ - Quyết định ai mặc áo gì với .call(), .apply(), .bind()

...thì this từ cơn ác mộng trở thành cơ hội để hiểu sâu bản chất

Thử thách cuối cho bạn đọc

Anh em đoán xem đoạn code này in ra gì:

const starbucks = {
  brand: "Starbucks",
  specialRecipe: function() {
    const secretIngredient = () => {
      console.log(`${this.brand} thêm nguyên liệu bí mật!`);
    };
    secretIngredient();
  }
};

const highlands = {
  brand: "Highlands"
};

starbucks.specialRecipe.call(highlands); // ???

Bài viết liên quan

Đừng đổ lỗi cho tối ưu hiệu năng nữa: Ứng dụng của bạn giật lag, có thể là do thiết kế sản phẩm quá tệ
Frontend
17/03/2026 · 8 phút đọc

Đừng đổ lỗi cho tối ưu hiệu năng nữa: Ứng dụng của bạn giật lag, có thể là do thiết kế sản phẩm quá tệ

Chắc hẳn mỗi khi chúng ta code xong một trang web và deploy lên production thì có một điều chúng ta khá quan tâm là Tối ưu hiệu năng (Performance Optimization). Trên mạng có nhiều bài viết chứa những thuật ngữ nghe rất đao to búa lớn: * Sử dụng Virtual List (danh sách ảo) để tối ưu việc render danh sách dài... * Sử dụng Web Worker để đẩy các tính toán phức tạp ra khỏi luồng chính (main thread)... * Sử dụng WASM để viết lại thuật toán lõi... Sau khi viết vài bài về tối ưu hiệu năng, cũng nh

Chi tiết bài viết
Chuyện gì thực sự xảy ra ở trình duyệt sau khi nhấn F5?
Frontend
11/03/2026 · 11 phút đọc

Chuyện gì thực sự xảy ra ở trình duyệt sau khi nhấn F5?

Trong lập trình frontend, "làm mới trang" trông có vẻ là một thao tác đơn giản, nhưng ẩn sau đó là một luồng phối hợp phức tạp giữa giao tiếp mạng (network communication), chiến lược cache (caching strategy) và engine render (rendering engine). Đặc biệt là khi nhấn F5, nó không phải là "tải lại hoàn toàn", cũng không phải là "dùng trực tiếp cache ở local", mà là một cơ chế xác thực thông minh nằm giữa hai trạng thái này. Để thực sự làm chủ các kỹ năng tối ưu hóa hiệu năng và debug frontend, bạn

Chi tiết bài viết
Server DTO: Nên giữ nguyên hay chuyển đổi?
Frontend
04/03/2026 · 12 phút đọc

Server DTO: Nên giữ nguyên hay chuyển đổi?

Trong các dự án mà Backend và Frontend được phát triển hoàn toàn tách biệt, chắc hẳn không ít lần chúng ta phải đau đầu với câu hỏi: "Dữ liệu server trả về thì nên xài luôn hay phải xào nấu lại?". Nếu dạo quanh các diễn đàn công nghệ hay đọc các bài thảo luận trên mạng, bạn sẽ thấy cuộc tranh luận về cách xử lý dữ liệu từ API này dường như chưa bao giờ có hồi kết. Cốt lõi của vấn đề luôn xoay quanh hai luồng quan điểm cực kỳ quen thuộc: "Dữ liệu backend trả về sao thì cứ tận dụng nguyên xi như

Chi tiết bài viết
Đừng lạm dụng useMemo nữa! Đây mới là Best Practice chuẩn xác dành cho bạn
Frontend
25/02/2026 · 12 phút đọc

Đừng lạm dụng useMemo nữa! Đây mới là Best Practice chuẩn xác dành cho bạn

useMemo là một React Hook giúp chúng ta ghi nhớ kết quả tính toán giữa các lần render để tối ưu hiệu năng trong một số trường hợp. Tuy nhiên, có một thực trạng đang diễn ra: người không biết thì chẳng bao giờ dùng, còn người đã biết thì lại lạm dụng nó ở mọi lúc, mọi nơi. Bài viết này sẽ giúp bạn hiểu rõ thực sự thì trong những trường hợp nào chúng ta mới nên sử dụng useMemo. Cú pháp tổng quát: useMemo hoạt động như thế nào? Ở lần render đầu tiên, useMemo sẽ thực thi hàm calculateValue (khôn

Chi tiết bài viết
Sydexa
Sydexa
SydexaSydexa

Nền tảng học lập trình với animation trực quan và bài tập tương tác, giúp bạn hiểu sâu thay vì chỉ đọc lý thuyết.

Sydexa FanpageBackend GroupFrontend Group

We learn, We share, We grow

Powered By
Cộng đồng System Design Việt Nam

contact@sydexa.com
0971489013