Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> JavaScript

Cơ chế từ khóa 'this' trong JavaScript

this trong JavaScript là contextual keyword – giá trị được xác định bởi cách hàm được gọi (call-site), không phải nơi hàm được định nghĩa. Đây là khái niệm quan trọng và thường gây nhầm lẫn nhất.

4 Quy tắc xác định this (Priority Order)

1. New Binding (Ưu tiên cao nhất)

Gọi hàm với new → this = instance mới tạo.


function Person(name) {
  this.name = name;
}
const an = new Person("An");
console.log(an.name); // "An"

2. Explicit Binding (call, apply, bind)

Gọi hàm với .call(), .apply(), .bind() → this = đối số đầu tiên.


function greet(greeting) {
  console.log(`${greeting}, ${this.name}`);
}

const user = { name: "An" };
greet.call(user, "Xin chào");     // "Xin chào, An"
greet.apply(user, ["Chào"]);      // "Chào, An"
const bound = greet.bind(user);
bound("Hello");                   // "Hello, An"

3. Implicit Binding (Object method call)

Gọi hàm như method của object: obj.method() → this = obj.


const user = {
  name: "An",
  greet() { console.log(`Hi, ${this.name}`); }
};
user.greet(); // "Hi, An" - this = user

// ⚠️ Mất binding khi gán cho biến
const greetFn = user.greet;
greetFn(); // "Hi, undefined" (strict mode) hoặc "Hi, " (sloppy mode - this = window)

4. Default Binding (Mặc định)

Gọi hàm thường: func() → this = globalThis (window browser, global Node). Strict mode: this = undefined.


function foo() { console.log(this); }
foo(); // window (sloppy) / undefined (strict)

"use strict";
function bar() { console.log(this); }
bar(); // undefined

Arrow Function: Lexical this

Arrow function KHÔNG CÓ this riêng – nó kế thừa this từ scope bao quanh (lexical scoping).


const user = {
  name: "An",
  regular() { console.log(this.name); }, // this = user
  arrow: () => console.log(this.name)    // this = outer scope (window/module)
};

user.regular(); // "An"
user.arrow();   // undefined (hoặc window.name)

Ví dụ từ bài gốc


var college = {
  subject: "Maths",
  lecturer: "Amy",
  details: function() {
    document.write(this.subject); // this = college
  }
};
college.details(); // "Maths"

Các tình huống dễ bị lỗi (Gotchas)

Tình huốngVấn đềGiải pháp
Callback / Event handlerthis = element (event) hoặc undefinedArrow function, bind, hoặc e.currentTarget
Method gán cho biếnMất binding (this = global/undefined)bind() hoặc arrow function property
Nested functionInner function this = global/undefinedArrow function, const self = this, bind
setTimeout/Intervalthis = global/undefinedArrow function hoặc bind

Best Practice Hiện Đại

  1. Dùng Arrow function cho callback, method không cần dynamic this.
  2. Dùng Method shorthand trong object/class: method() {}.
  3. Cần dynamic this → dùng function() {} + .bind(this) hoặc call/apply.
  4. Luôn bật Strict Mode ("use strict" hoặc ES Modules) – this = undefined thay vì window giúp bắt bug sớm.
  5. Class fields (ES2022): method = () => {} – auto-bind this.

// Class field arrow function - auto bind
class Component {
  state = { count: 0 };
  handleClick = () => {
    console.log(this.state.count); // this luôn = instance
  };
  render() {
    return ;
  }
}