Giải thích vòng lặp for…in trong JavaScript: Cú pháp, Trường hợp sử dụng và Thực hành tốt nhất

目次

1. Introduction|What Problems Can the for…in Statement Solve?

JavaScript là một trong những ngôn ngữ lập trình được sử dụng rộng rãi nhất trong phát triển web. Trong số nhiều tính năng của nó, vòng lặp là thiết yếu để xử lý dữ liệu lặp đi lặp lại. Đặc biệt, câu lệnh for…in hữu ích cho việc lặp qua các thuộc tính của một đối tượng.

Purpose of This Article

Trong bài viết này, chúng tôi sẽ trình bày chi tiết các điểm sau:

  • Cú pháp cơ bản và cách sử dụng vòng lặp for…in trong JavaScript
  • Những lưu ý khi sử dụng nó với mảng
  • Sự khác biệt so với các cấu trúc vòng lặp khác (for…of và forEach)
  • Các lỗi thường gặp và cách khắc phục

What You’ll Learn

  • Cách xử lý hiệu quả các thuộc tính của đối tượng và các phần tử của mảng
  • Những lưu ý và cách sử dụng an toàn câu lệnh for…in
  • Các ví dụ mã thực tế và so sánh hiệu năng

Bài viết được cấu trúc để cung cấp kiến thức hữu ích cho cả người mới bắt đầu và các nhà phát triển JavaScript trung cấp. Hãy bắt đầu ở phần tiếp theo với những kiến thức cơ bản về câu lệnh for…in.

2. What is the JavaScript for…in Statement?【Basic Explanation】

Trong JavaScript, câu lệnh for…in được dùng để lặp qua các thuộc tính của một đối tượng. Cú pháp này đặc biệt phù hợp với các đối tượng, cho phép bạn xử lý từng tên thuộc tính (key) một cách tuần tự.

Basic Syntax

Đây là cú pháp cơ bản của vòng lặp for…in:

for (variable in object) {
  // Repeated processing
}

Parameter Explanation:

  • variable : Lưu trữ tên thuộc tính hiện tại (key).
  • object : Đối tượng mục tiêu mà bạn muốn lặp qua.

Usage Example: Enumerating Object Properties

const person = {
  name: "Taro",
  age: 25,
  city: "Tokyo"
};

for (const key in person) {
  console.log(`${key}: ${person[key]}`);
}

Output:

name: Taro
age: 25
city: Tokyo

Caution: Order of Enumerated Properties

Thứ tự các thuộc tính trong vòng lặp for…in không được đảm bảo. Theo đặc tả JavaScript, thứ tự có thể không khớp với thứ tự chèn khi các key là chuỗi. Nếu bạn cần một thứ tự nghiêm ngặt, hãy sử dụng các phương pháp thay thế như Object.keys().

Summary of Features

  1. Dễ dàng lấy các key của đối tượng: Hữu ích khi truy cập động tên thuộc tính.
  2. Chỉ các thuộc tính có thể liệt kê được mới được mục tiêu: Các thuộc tính không thể liệt kê (enumerable: false) sẽ bị loại bỏ.
  3. Các thuộc tính kế thừa từ prototype cũng sẽ được liệt kê: Điều này có thể gây ra vấn đề, sẽ được giải thích trong phần tiếp theo.

3. Arrays and the for…in Statement|Key Points to Watch

Câu lệnh for…in trong JavaScript được thiết kế để liệt kê các thuộc tính của đối tượng, nhưng nó cũng có thể được dùng với mảng. Tuy nhiên, có một số lưu ý quan trọng khi áp dụng nó cho mảng. Hãy xem xét hành vi và các cạm bẫy chi tiết dưới đây.

Basic Behavior with Arrays

Xem ví dụ sau:

const fruits = ["Apple", "Banana", "Orange"];

for (const index in fruits) {
  console.log(index, fruits[index]);
}

Output:

0 Apple  
1 Banana  
2 Orange

Caution 1: Prototype Properties May Be Enumerated

Array.prototype.newMethod = function () {
  return "New Method";
};

for (const index in fruits) {
  console.log(index, fruits[index]);
}

Output:

0 Apple  
1 Banana  
2 Orange  
newMethod undefined

Solution:

for (const index in fruits) {
  if (fruits.hasOwnProperty(index)) {
    console.log(index, fruits[index]);
  }
}

Caution 2: Order Is Not Guaranteed

const data = [];
data[10] = "Apple";
data[1] = "Banana";
data[5] = "Orange";

for (const index in data) {
  console.log(index, data[index]);
}

Output:

1 Banana  
5 Orange  
10 Apple

Caution 3: Indexes Are Treated as Strings

const numbers = [10, 20, 30];
for (const index in numbers) {
  console.log(typeof index); // "string"
}

Solution:

for (const index in numbers) {
  const numIndex = parseInt(index, 10);
  console.log(numIndex, numbers[numIndex]);
}

Tóm tắt

  • Câu lệnh for…in phù hợp hơn cho các đối tượng so với mảng.
  • Để xử lý thứ tự và chỉ số số, for…of hoặc vòng lặp for truyền thống được khuyến nghị.

4. Sự khác biệt giữa for…in và for…of【Bảng so sánh】

Trong JavaScript, cả for…infor…of đều có sẵn để lặp, nhưng các trường hợp sử dụng và hành vi của chúng khác nhau.

So sánh cú pháp

for…in:

const obj = { a: 1, b: 2, c: 3 };
for (const key in obj) {
  console.log(key); // Retrieves keys
}

for…of:

const arr = [10, 20, 30];
for (const value of arr) {
  console.log(value); // Retrieves values
}

Bảng so sánh

Aspectfor…infor…of
TargetObjects and arraysArrays and iterable objects
OutputProperty names (keys)Values themselves
Prototype EnumerationMay include prototype propertiesDoes not enumerate prototype properties
Order GuaranteeNot guaranteedGuaranteed

Ví dụ thực tế|Xử lý mảng

const arr = ['a', 'b', 'c'];

// for...in
for (const index in arr) {
  console.log(index); // Output: 0, 1, 2
}

// for...of
for (const value of arr) {
  console.log(value); // Output: 'a', 'b', 'c'
}

Tóm tắt

  • for…in: Tốt nhất cho việc xử lý các khóa đối tượng.
  • for…of: Tốt nhất cho mảng và các đối tượng có thể lặp.

5. Sử dụng thực tế: Ứng dụng và Best Practices của câu lệnh for…in

Ở đây, chúng ta sẽ khám phá các ứng dụng thực tế của câu lệnh for…in trong JavaScript và giới thiệu các best practices hữu ích trong phát triển thực tế.

1. Ví dụ 1|Lọc thuộc tính đối tượng

const user = {
  name: "Tanaka",
  age: 30,
  email: "tanaka@example.com",
  password: "secret123"
};

const publicData = {};
for (const key in user) {
  if (key !== "password") {
    publicData[key] = user[key];
  }
}
console.log(publicData);

Đầu ra:

{ name: 'Tanaka', age: 30, email: 'tanaka@example.com' }

2. Ví dụ 2|Xử lý đối tượng lồng nhau

const data = {
  user: {
    name: "Sato",
    info: {
      age: 28,
      city: "Osaka"
    }
  }
};

function printNested(obj) {
  for (const key in obj) {
    if (typeof obj[key] === "object") {
      printNested(obj[key]);
    } else {
      console.log(`${key}: ${obj[key]}`);
    }
  }
}

printNested(data);

Đầu ra:

name: Sato
age: 28
city: Osaka

3. Best Practice|Loại trừ thuộc tính prototype

const obj = { a: 1, b: 2 };
Object.prototype.c = 3;

for (const key in obj) {
  if (obj.hasOwnProperty(key)) {
    console.log(`${key}: ${obj[key]}`);
  }
}

Đầu ra:

a: 1
b: 2

Tóm tắt

  • Chúng ta đã giới thiệu các trường hợp sử dụng phù hợp cho việc lọc và xử lý đối tượng lồng nhau.
  • Sử dụng hasOwnProperty() để ngăn chặn việc liệt kê kế thừa prototype không mong muốn.

6. Lỗi phổ biến và Giải pháp với for…in【Thân thiện với người mới bắt đầu】

1. Ví dụ lỗi 1|Thuộc tính prototype được liệt kê

const obj = { a: 1, b: 2 };
Object.prototype.c = 3;

for (const key in obj) {
  console.log(key, obj[key]);
}

Đầu ra:

a 1
b 2
c 3

Giải pháp:

for (const key in obj) {
  if (obj.hasOwnProperty(key)) {
    console.log(key, obj[key]);
  }
}

2. Ví dụ lỗi 2|Sử dụng for…in với mảng

const arr = [10, 20, 30];
Array.prototype.extra = "Additional Data";

for (const index in arr) {
  console.log(index, arr[index]);
}

Đầu ra:

0 10
1 20
2 30
extra undefined

Giải pháp:

for (const value of arr) {
  console.log(value);
}

3. Ví dụ lỗi 3|Xử lý giá trị không xác định

const obj = { a: 1, b: undefined, c: 3 };

for (const key in obj) {
  console.log(key, obj[key]);
}

Giải pháp:

for (const key in obj) {
  const value = obj[key] ?? "Default Value";
  console.log(key, value);
}

Tóm tắt

  • Vấn đề thuộc tính prototype: Sử dụng hasOwnProperty().
  • Xử lý mảng: Ưu tiên for…of hoặc forEach thay vì for…in.
  • Giá trị không xác định: Gán giá trị mặc định với toán tử hợp nhất nullish ( ?? ).

7. Kiểm tra hiệu suất và Các lựa chọn thay thế cho for…in

1. So sánh hiệu suất

Câu lệnh for…in:

const obj = { a: 1, b: 2, c: 3 };
console.time("for...in");
for (const key in obj) {
  console.log(key, obj[key]);
}
console.timeEnd("for...in");

Object.keys():

console.time("Object.keys");
Object.keys(obj).forEach(key => {
  console.log(key, obj[key]);
});
console.timeEnd("Object.keys");

2. Kết quả so sánh ví dụ

for...in: 0.015ms
Object.keys: 0.005ms

3. Các lựa chọn thay thế được đề xuất

  • Xử lý đối tượng: Nên dùng Object.keys() để có hiệu năng và độ an toàn tốt hơn.
  • Xử lý mảng: Sử dụng for…of hoặc forEach để lặp nhanh hơn và đáng tin cậy hơn.

Tóm tắt

  • Câu lệnh for…in tiện lợi, nhưng hãy chọn cấu trúc vòng lặp phù hợp nhất dựa trên hiệu năng và độ an toàn.

8. Kết luận|Hiểu về câu lệnh for…in và các bước tiếp theo

1. Những điểm chính cần nhớ

  1. Cú pháp cơ bản và cách sử dụng for…in:
  • Được dùng để lặp qua tên các thuộc tính của đối tượng.
  • Chuyên dùng cho các khóa của đối tượng, không phải mảng.
  1. Lưu ý khi sử dụng với m:
  • Thứ tự không được đảm bảo, và các thuộc tính trong chuỗi prototype có thể được bao gồm.
  • Đối với mảng, nên dùng for…of hoặc forEach() thay thế.
  1. Sự khác nhau giữa for…in và for…of:
  • for…in: Lặp qua tên thuộc tính (khóa).
  • for…of: Lặp qua giá trị thực của mảng hoặc các đối tượng có thể lặp.
  1. Ứng dụng thực tế và các thực hành tốt:
  • Xử lý các đối tượng lồng nhau bằng đệ quy.
  • Loại trừ kế thừa prototype bằng hasOwnProperty().
  • Cải thiện hiệu năng và độ an toàn bằng Object.keys() hoặc Object.entries().
  1. Tối ưu hoá hiệu năng:
  • Object.keys() + forEach() được khuyến nghị để đảm bảo thứ tự và hiệu quả, làm cho nó trở thành một lựa chọn an toàn hơn so với for…in.

2. Câu trả lời cho các câu hỏi thường gặp

Câu hỏi 1. Tôi có nên tránh sử dụng câu lệnh for…in không?

  • Đáp: Nó phù hợp để liệt kê các thuộc tính của đối tượng, nhưng đối với mảng hoặc các tác vụ yêu cầu hiệu cao, for…of hoặc Object.keys() an toàn và hiệu quả hơn.

Câu hỏi 2. Các thuộc tính prototype sẽ luôn được liệt kê không?

  • Đáp: Có. Theo đặc tả, các thuộc tính prototype kế thừa cũng sẽ được bao gồm. Hãy dùng hasOwnProperty() để tránh vấn đề này.

Câu hỏi 3. Vòng lặp nào là tốt nhất cho mảng và đối tượng?

  • Đối tượng: Dùng for…in hoặc Object.keys().
  • Mảng: Dùng for…of hoặc forEach().

3. Các bước tiếp theo|Những gì cần học tiếp

  1. Iterables và các đối tượng Iterable:
  • Các cấu trúc dữ liệu như Map, Set, WeakMap, WeakSet và các vòng lặp để xử lý chúng.
  1. Hàm bậc cao để xử lý dữ liệu:
  • Cách sử dụng thực tế của map(), filter(), reduce().
  1. Kỹ thuật nâng cao cho Object và Array:

ử dụng Object.values()Object.entries()* để xử lý dữ liệu hiệu quả.

  1. Các tính năng hiện đại của JavaScript:
  • Các tính năng ES6+ như ** operatortructuring** để viết code gọn gàng hơn.
  1. Lập trình bất đồng bộ với Promise/Async/Await:
  • Áp dụng vòng lặp trong xử lý thời gian thực như lấy dữ liệu và xử lý đối tượng động.

4. Suy nghĩ cuối cùng|Làm chủ vòng lặp JavaScript

Trong bài viết này, chúng tôi tập trung vào **câu lệnh for…in của JavaScript, bao gồm cách sử dụng cơ bản, các ứng dụng nâng cao, những bẫy và lựa chọn thay thế.

Những điểm quan trọng nhất:

  • for…in là lý tưởng để liệt kê các thuộc tính của đối tượng, nhưng đối với mảng hoặc các tác vụ tập trung vào hiệu năng, nên sử dụng các phương pháp khác.
  • Luôn tuân thủ các thực hành tốt và biện pháp an toàn để tránh lỗi và hành vi không mong muốn trong code.

Bước tiếp theo! Nâng cao hiểu biết của bạn về các phương pháp thay thế và hàm bậc cao để đưa kỹ năng JavaScript của bạn lên một tầm cao mới.

広告