Các phương thức của Object trong JavaScript

Javascript nâng cao | by Học Javascript

Trong JavaScript, Object là một trong những kiểu dữ liệu quan trọng và được sử dụng phổ biến nhất. Để làm việc với Object hiệu quả, JavaScript cung cấp nhiều phương thức tích hợp giúp thao tác, truy vấn, bảo vệ và mở rộng Object một cách linh hoạt.

Việc nắm vững các phương thức này không chỉ giúp lập trình viên viết mã ngắn gọn, tối ưu mà còn cải thiện hiệu suất của ứng dụng. Trong bài viết này, chúng ta sẽ cùng tìm hiểu các phương thức quan trọng của Object trong JavaScript và cách chúng được áp dụng trong thực tế.

Nhóm phương thức thao tác với Object trong JavaScript

Nhóm phương thức này cho phép chúng ta sao chép, tạo mới, hoặc chỉnh sửa các thuộc tính trong một object. Đây là những phương thức quan trọng giúp thao tác với object một cách linh hoạt và tối ưu hơn.

Object.assign(target, ...sources)

Phương thức Object.assign() được sử dụng để sao chép thuộc tính từ một hoặc nhiều object source vào object target.

Cách hoạt động:

  • Sao chép các thuộc tính liệt kê được (enumerable) từ các object nguồn (sources) vào object đích (target).

  • Nếu các thuộc tính trùng nhau, giá trị của thuộc tính sẽ bị ghi đè theo thứ tự của source.

  • Chỉ sao chép giá trị, không sao chép prototype hoặc thuộc tính không liệt kê được.

Ví dụ sử dụng:

const obj1 = { a: 1, b: 2 };
const obj2 = { b: 3, c: 4 };

const result = Object.assign({}, obj1, obj2);
console.log(result); // { a: 1, b: 3, c: 4 }
  • Sao chép và hợp nhất object.

  • Tạo một bản sao nông (shallow copy) của object.

Object.create(proto, propertiesObject)

Phương thức Object.create() được sử dụng để tạo một object mới với một object khác làm prototype.

Cách hoạt động:

  • Nếu truyền null, object mới sẽ không có prototype.

  • Nếu truyền một object proto, object mới sẽ kế thừa từ prototype đó.

  • Có thể thêm các thuộc tính ban đầu bằng propertiesObject.

Ví dụ sử dụng:

const personProto = {
  greet() {
    console.log(`Hello, my name is ${this.name}`);
  }
};

const person = Object.create(personProto);
person.name = "Alice";
person.greet(); // Hello, my name is Alice
  • Tạo object kế thừa từ một prototype cụ thể mà không cần dùng class.

  • Tạo object với cấu trúc linh hoạt hơn so với new Object().

Object.defineProperty(obj, prop, descriptor)

Phương thức Object.defineProperty() cho phép thêm hoặc chỉnh sửa một thuộc tính của object với mô tả chi tiết hơn.

Cách hoạt động:

  • Kiểm soát quyền truy cập, khả năng chỉnh sửa, xóa thuộc tính.

  • Cho phép tạo getter và setter cho thuộc tính.

Ví dụ sử dụng:

const person = {};

Object.defineProperty(person, "name", {
  value: "Alice",
  writable: false,  // Không thể thay đổi giá trị
  enumerable: true, // Có thể liệt kê khi duyệt qua object
  configurable: false // Không thể xóa hoặc thay đổi thuộc tính
});

console.log(person.name); // Alice
person.name = "Bob"; // Không thay đổi vì writable: false
console.log(person.name); // Alice
  • Định nghĩa thuộc tính với quyền kiểm soát chặt chẽ.

  • Tạo các thuộc tính chỉ đọc hoặc ẩn khỏi vòng lặp for...in.

Object.defineProperties(obj, props)

Phương thức Object.defineProperties() cho phép định nghĩa nhiều thuộc tính cùng lúc cho một object.

Cách hoạt động:

  • Tương tự Object.defineProperty(), nhưng cho phép định nghĩa nhiều thuộc tính trong một lần gọi.

Ví dụ sử dụng:

const user = {};

Object.defineProperties(user, {
  name: {
    value: "Charlie",
    writable: true
  },
  age: {
    value: 25,
    writable: false
  }
});

console.log(user.name); // Charlie
console.log(user.age);  // 25
user.age = 30; // Không thay đổi vì writable: false
console.log(user.age);  // 25
  • Khai báo nhiều thuộc tính cùng lúc với mô tả chi tiết.

  • Hữu ích khi tạo các object có kiểm soát truy cập nghiêm ngặt.

Nhóm phương thức kiểm tra và truy vấn Object trong JavaScript

Nhóm phương thức này giúp chúng ta lấy danh sách các key, value, cặp key-value và kiểm tra sự tồn tại của thuộc tính trong một object. Những phương thức này rất hữu ích khi làm việc với dữ liệu trong JavaScript.

Object.keys(obj) – Lấy danh sách tất cả các key của object

Cách hoạt động:

  • Trả về một mảng chứa tất cả key của object.

  • Chỉ lấy các thuộc tính có thể liệt kê được (enumerable properties).

  • Không lấy thuộc tính trong prototype.

Ví dụ sử dụng:

const user = {
  name: "Alice",
  age: 25,
  city: "New York"
};

console.log(Object.keys(user)); 
// Output: ["name", "age", "city"]
  • Duyệt qua tất cả thuộc tính của object.

  • Kiểm tra số lượng thuộc tính có trong object.

Object.values(obj) – Lấy danh sách tất cả các giá trị của object

Cách hoạt động:

  • Trả về một mảng chứa tất cả giá trị của object.

  • Chỉ lấy các thuộc tính có thể liệt kê được.

Ví dụ sử dụng:

console.log(Object.values(user)); 
// Output: ["Alice", 25, "New York"]
  • Lấy danh sách các giá trị của object để xử lý.

  • Áp dụng với map(), filter(), hoặc reduce().

Ví dụ ứng dụng với reduce()

Tính tổng số lượng sản phẩm trong giỏ hàng:

const cart = {
  apple: 2,
  banana: 5,
  orange: 3
};

const totalItems = Object.values(cart).reduce((sum, count) => sum + count, 0);
console.log(totalItems); // 10

Object.entries(obj) – Lấy danh sách cặp [key, value] của object

Cách hoạt động:

  • Trả về một mảng chứa các cặp [key, value] của object.

  • Chỉ lấy các thuộc tính có thể liệt kê được.

  • Rất hữu ích khi làm việc với các cấu trúc như Map.

Ví dụ sử dụng:

console.log(Object.entries(user)); 
// Output: [["name", "Alice"], ["age", 25], ["city", "New York"]]

Ứng dụng:

  • Duyệt qua tất cả thuộc tính của object bằng forEach().

Object.entries(user).forEach(([key, value]) => {
  console.log(`${key}: ${value}`);
});

Output:

name: Alice
age: 25
city: New York

Chuyển đổi Object thành Map:

const userMap = new Map(Object.entries(user));
console.log(userMap.get("name")); // Alice

Object.hasOwnProperty(prop) – Kiểm tra xem object có thuộc tính cụ thể không

Cách hoạt động:

  • Trả về true nếu object thuộc tính prop.

  • Trả về false nếu không có hoặc nếu thuộc tính nằm trong prototype.

Ví dụ sử dụng:

console.log(user.hasOwnProperty("name")); // true
console.log(user.hasOwnProperty("email")); // false

Kiểm tra trước khi truy cập một thuộc tính để tránh lỗi undefined.

if (user.hasOwnProperty("email")) {
  console.log(user.email);
} else {
  console.log("Không có email!");
}
  • Phân biệt thuộc tính của object và thuộc tính trong prototype.

Lưu ý:
hasOwnProperty() chỉ kiểm tra thuộc tính của chính object đó, không kiểm tra trong prototype chain.

const person = { name: "Bob" };
console.log(person.hasOwnProperty("toString")); // false (vì toString thuộc prototype)

Object.getOwnPropertyNames(obj) – Lấy danh sách tất cả thuộc tính của object, kể cả thuộc tính không liệt kê

Cách hoạt động:

  • Trả về một mảng chứa tất cả tên thuộc tính của object, bao gồm cả thuộc tính không thể liệt kê được.

  • Không lấy thuộc tính trong prototype.

Ví dụ sử dụng:

const secretUser = Object.create({}, {
  id: { value: 123, enumerable: false },
  username: { value: "admin", enumerable: true }
});

console.log(Object.keys(secretUser)); // ["username"]
console.log(Object.getOwnPropertyNames(secretUser)); // ["id", "username"]
  • Lấy danh sách tất cả thuộc tính, kể cả thuộc tính ẩn (non-enumerable).

  • Hữu ích khi làm việc với object có các thuộc tính đặc biệt hoặc sử dụng defineProperty().

Phương thức Công dụng Đặc điểm chính
Object.keys(obj) Lấy danh sách tất cả key của object Chỉ lấy thuộc tính enumerable
Object.values(obj) Lấy danh sách tất cả giá trị của object Chỉ lấy thuộc tính enumerable
Object.entries(obj) Lấy danh sách cặp [key, value] của object Chỉ lấy thuộc tính enumerable
Object.hasOwnProperty(prop) Kiểm tra xem object có thuộc tính cụ thể không Không kiểm tra trong prototype chain
Object.getOwnPropertyNames(obj) Lấy danh sách tất cả thuộc tính, kể cả không enumerable Không lấy thuộc tính trong prototype

Nhóm phương thức bảo vệ và thao tác với Prototype trong JavaScript

Nhóm phương thức này giúp bảo vệ object khỏi bị thay đổi và quản lý prototype của object. Những phương thức này rất hữu ích khi muốn kiểm soát tính toàn vẹn của dữ liệu trong ứng dụng JavaScript.

Object.freeze(obj) – Đóng băng object, không thể sửa đổi hoặc thêm/xóa thuộc tính

Cách hoạt động:

  • Khi một object bị "đóng băng" bằng Object.freeze(), nó sẽ trở thành bất biến (immutable).

  • Không thể thay đổi, thêm, hoặc xóa thuộc tính của object.

  • Các thuộc tính bên trong object không bị đóng băng nếu chúng là object lồng nhau (shallow freeze).

Ví dụ sử dụng:

const user = { name: "Alice", age: 25 };
Object.freeze(user);

user.age = 30;  //  Không thể thay đổi
user.city = "New York";  //  Không thể thêm mới
delete user.name;  // Không thể xóa thuộc tính

console.log(user);  // { name: "Alice", age: 25 }

Kiểm tra object có bị đóng băng không?

console.log(Object.isFrozen(user)); // true
  • Dùng để bảo vệ dữ liệu quan trọng không bị thay đổi.

  • Hữu ích khi làm việc với hằng số cấu hình trong ứng dụng.

Lưu ý:

  • Object.freeze() chỉ đóng băng cấp đầu tiên (shallow freeze).

  • Nếu object có thuộc tính là object khác, thuộc tính bên trong vẫn có thể thay đổi.

const obj = { nested: { value: 10 } };
Object.freeze(obj);
obj.nested.value = 20; //  Thuộc tính bên trong vẫn thay đổi được

Object.seal(obj) – Ngăn chặn thêm hoặc xóa thuộc tính nhưng vẫn có thể chỉnh sửa giá trị

Cách hoạt động:

  • Ngăn không cho thêm hoặc xóa thuộc tính.

  • Nhưng vẫn có thể sửa đổi giá trị của thuộc tính hiện tại.

Ví dụ sử dụng:

const user = { name: "Alice", age: 25 };
Object.seal(user);

user.age = 30;  // Có thể sửa đổi
user.city = "New York";  //  Không thể thêm mới
delete user.name;  // Không thể xóa thuộc tính

console.log(user);  // { name: "Alice", age: 30 }

Kiểm tra object có bị seal không?

console.log(Object.isSealed(user)); // true
  • Khi cần bảo vệ object, nhưng vẫn muốn cho phép chỉnh sửa dữ liệu hiện có.

  • Ví dụ: Bảo vệ thông tin user nhưng vẫn cho phép cập nhật giá trị.

Lưu ý:

  • Không giống như Object.freeze(), Object.seal() không làm cho giá trị bất biến, chỉ chặn việc thêm hoặc xóa thuộc tính.

Object.preventExtensions(obj) – Ngăn chặn thêm thuộc tính mới vào object

Cách hoạt động:

  • Sau khi gọi Object.preventExtensions(), object không thể thêm thuộc tính mới.

  • Nhưng vẫn có thể chỉnh sửa và xóa các thuộc tính hiện có.

Ví dụ sử dụng:

const user = { name: "Alice", age: 25 };
Object.preventExtensions(user);

user.age = 30;  //  Có thể sửa đổi
delete user.name;  //  Có thể xóa
user.city = "New York";  //  Không thể thêm mới

console.log(user);  // { age: 30 }

Kiểm tra object có bị ngăn chặn mở rộng không?

console.log(Object.isExtensible(user)); // false
  • Ngăn chặn việc mở rộng object một cách không mong muốn.

  • Hữu ích khi làm việc với các cấu trúc dữ liệu cố định.

Lưu ý:

  • Không giống như Object.seal(), bạn vẫn có thể xóa thuộc tính.

  • Nhưng không thể thêm mới.

Object.getPrototypeOf(obj) – Lấy prototype của một object

Cách hoạt động:

  • Trả về prototype của object.

  • Nếu object không có prototype, trả về null.

Ví dụ sử dụng:

const person = { name: "Bob" };
const proto = Object.getPrototypeOf(person);

console.log(proto); // {} (Object prototype)
console.log(Object.getPrototypeOf(proto)); // null
  • Kiểm tra xem object được kế thừa từ prototype nào.

  • Hữu ích khi làm việc với prototype chain.

Ví dụ kiểm tra object có kế thừa từ prototype không?

console.log(proto === Object.prototype); // true

Object.setPrototypeOf(obj, prototype) – Thiết lập prototype cho object

Cách hoạt động:

  • Thay đổi prototype của object.

  • Dùng để kế thừa phương thức từ prototype khác.

Ví dụ sử dụng:

const animal = {
  speak() {
    console.log("Animal sound");
  }
};

const dog = { breed: "Golden Retriever" };

// Gán prototype của animal cho dog
Object.setPrototypeOf(dog, animal);

dog.speak(); // "Animal sound"
  • Thay đổi prototype của object một cách linh hoạt.

  • Tạo hệ thống kế thừa trong JavaScript.

Lưu ý:

  • Thay đổi prototype có thể làm giảm hiệu suất vì JavaScript tối ưu hóa object khi prototype không thay đổi.

  • Thay vì Object.setPrototypeOf(), nên sử dụng Object.create().

const dog = Object.create(animal);
dog.breed = "Golden Retriever";
dog.speak(); // "Animal sound"

Kết bài

Trong JavaScript, các phương thức của Object đóng vai trò quan trọng trong việc quản lý, bảo vệ và thao tác với object. Từ việc sao chép, truy vấn, kiểm tra, bảo vệ cho đến thao tác với prototype, mỗi phương thức đều có ứng dụng cụ thể giúp lập trình viên tối ưu hóa mã nguồn và đảm bảo tính nhất quán của dữ liệu.

Việc hiểu và sử dụng thành thạo các phương thức như Object.freeze(), Object.seal(), Object.getPrototypeOf() hay Object.assign() sẽ giúp bạn kiểm soát tốt hơn cách dữ liệu được lưu trữ và xử lý trong JavaScript. Đồng thời, nắm vững cách thức hoạt động của prototype cũng sẽ giúp bạn làm chủ mô hình kế thừa của JavaScript, từ đó viết mã hiệu quả, dễ bảo trì và có hiệu suất cao hơn.

Hy vọng bài viết này sẽ giúp bạn có cái nhìn tổng quan và ứng dụng tốt hơn các phương thức của Object trong các dự án thực tế!

Bài viết liên quan