[MẸO] Mảng Javascript: Mẹo và thủ thuật cần thiết

By hungpd, at: 12:01 Ngày 01 tháng 3 năm 2025

Thời gian đọc ước tính: __READING_TIME__ minutes

[TIPS] Javascript Array: Essential Tips and Tricks
[TIPS] Javascript Array: Essential Tips and Tricks

[MẸO] Javascript Mảng: Mẹo và thủ thuật cần thiết


Mảng là một trong những cấu trúc dữ liệu được sử dụng phổ biến nhất trong JavaScript. Chúng cho phép chúng ta lưu trữ nhiều giá trị trong một biến duy nhất và đi kèm với các phương thức tích hợp mạnh mẽ giúp đơn giản hóa việc thao tác dữ liệu. Trong bài đăng trên blog này, chúng ta sẽ khám phá những mẹo cần thiết để làm việc với mảng hiệu quả, bao gồm các đoạn mã, giải thích và ưu điểm, nhược điểm của mỗi phương pháp.

 

1. Thêm và xóa phần tử


Push và Pop (Hành vi ngăn xếp)
 

  • push() thêm một phần tử vào cuối mảng.

  • pop() xóa phần tử cuối cùng.

 

Ví dụ:

let arr = [1, 2, 3];
arr.push(4);  // [1, 2, 3, 4]
arr.pop();   // [1, 2, 3]

 

Ưu điểm: Đơn giản và hiệu quả để sửa đổi cuối mảng.


Nhược điểm: Không hiệu quả đối với các mảng lớn nếu cần nhiều thao tác chèn/xóa.

 

Shift và Unshift (Hành vi hàng đợi)
 

  • unshift() thêm một phần tử vào đầu mảng.

  • shift() xóa phần tử đầu tiên.

 

Ví dụ:

let arr = [1, 2, 3];
arr.unshift(0);  // [0, 1, 2, 3]
arr.shift();     // [1, 2, 3]

 

Ưu điểm: Hữu ích để triển khai hàng đợi.


Nhược điểm: Chậm đối với các mảng lớn vì việc dịch chuyển các phần tử yêu cầu lập chỉ mục lại.

 

So sánh hiệu năng

// Ví dụ: So sánh hiệu năng của push/pop so với shift/unshift
let largeArray = Array.from({ length: 100000 }, (_, i) => i);

console.time("push/pop");
for (let i = 0; i < 1000; i++) {
  largeArray.push(i);
  largeArray.pop();
}
console.timeEnd("push/pop");

console.time("shift/unshift");
for (let i = 0; i < 1000; i++) {
  largeArray.unshift(i);
  largeArray.shift();
}
console.timeEnd("shift/unshift");


Giải thích: Như bạn có thể thấy từ các điểm chuẩn, các thao tác pushpop nhanh hơn đáng kể so với shiftunshift đối với các mảng lớn. Điều này là bởi vì shiftunshift yêu cầu lập chỉ mục lại tất cả các phần tử tiếp theo, đây là một thao tác tốn kém.

 

2. Sao chép mảng

 

Kỹ thuật Slice


Thay vì sửa đổi một mảng hiện có, bạn có thể muốn làm việc với một bản sao.

 

Ví dụ:

let arr = [1, 2, 3];
let copy1 = [...arr];    // Sử dụng toán tử spread
let copy2 = arr.slice(); // Sử dụng slice()

 

Ưu điểm: Cả hai phương pháp đều hiệu quả và ngăn chặn việc sửa đổi mảng gốc.


Nhược điểm: Không phù hợp để sao chép sâu (các mảng lồng nhau vẫn được tham chiếu).

 

Kỹ thuật sao chép sâu

// Ví dụ: Sao chép sâu sử dụng JSON.parse(JSON.stringify())
let nestedArray = [1, [2, 3], 4];
let deepCopy = JSON.parse(JSON.stringify(nestedArray));
deepCopy[1][0] = 99; // Sửa đổi bản sao

console.log(nestedArray); // Bản gốc không thay đổi
console.log(deepCopy); // Bản sao sâu phản ánh sự thay đổi

// Giải thích về những hạn chế:
// - Không hoạt động với hàm, undefined hoặc tham chiếu tuần hoàn.
// - Chậm hơn sao chép nông.

// Ví dụ sử dụng Lodash (nếu bạn muốn thêm):
// const _ = require('lodash');
// let deepCopyLodash = _.cloneDeep(nestedArray);

 

3. Các thao tác hàm trên mảng

 

Map, Filter và Reduce
 

  • map(): Biến đổi mỗi phần tử.

  • filter(): Chọn các phần tử dựa trên một điều kiện.

  • reduce(): Tính toán một giá trị duy nhất dựa trên mảng.

 

Ví dụ:

let numbers = [1, 2, 3, 4];
let doubled = numbers.map(n => n * 2);  // [2, 4, 6, 8]
let evens = numbers.filter(n => n % 2 === 0); // [2, 4]
let sum = numbers.reduce((acc, n) => acc + n, 0); // 10

 

Ưu điểm: Ngắn gọn, hiệu quả và thân thiện với lập trình hàm.


Nhược điểm: Tạo các mảng mới, có khả năng sử dụng nhiều bộ nhớ hơn.

 

Kỹ thuật nâng cao

// Ví dụ: Nhóm các đối tượng theo một thuộc tính
let people = [
  { name: 'Alice', age: 25 },
  { name: 'Bob', age: 30 },
  { name: 'Charlie', age: 25 },
];

let groupedByAge = people.reduce((acc, person) => {
  if (!acc[person.age]) {
    acc[person.age] = [];
  }
  acc[person.age].push(person);
  return acc;
}, {});

console.log(groupedByAge);

// Ví dụ: Tạo bản đồ tần số
let letters = ['a', 'b', 'a', 'c', 'b', 'b'];
let letterFrequency = letters.reduce((acc, letter) => {
  acc[letter] = (acc[letter] || 0) + 1;
  return acc;
}, {});
console.log(letterFrequency);


Giải thích: Phương thức reduce() cực kỳ mạnh mẽ để biến đổi dữ liệu phức tạp, chẳng hạn như nhóm các đối tượng hoặc tạo bản đồ tần số.

 

4. Tìm kiếm phần tử trong mảng

 

Sử dụng find()findIndex()
 

  • find() trả về phần tử đầu tiên khớp với điều kiện.

  • findIndex() trả về chỉ mục của phần tử khớp đầu tiên.

 

Ví dụ:

let users = [
  { id: 1, name: 'Alice' },
  { id: 2, name: 'Bob' }
];
let user = users.find(u => u.id === 2);  // { id: 2, name: 'Bob' }
let index = users.findIndex(u => u.id === 2);  // 1

 

Ưu điểm: Dễ dàng tìm kiếm các đối tượng trong mảng.


Nhược điểm: Dừng lại ở lần khớp đầu tiên, vì vậy nó không lý tưởng cho nhiều kết quả.

 

5. Kiểm tra phần tử

 

Sử dụng includes()


Phương thức includes() kiểm tra xem một mảng có chứa một giá trị cụ thể hay không.

 

Ví dụ:

let fruits = ['apple', 'banana', 'mango'];
console.log(fruits.includes('banana')); // true

 

Ưu điểm: Cú pháp đơn giản để kiểm tra sự tồn tại.


Nhược điểm: Chỉ hoạt động với các giá trị nguyên thủy (không phải đối tượng).

 

6. Xóa trùng lặp

 

Sử dụng Set


Một Set tự động xóa các giá trị trùng lặp khỏi một mảng.

 

Ví dụ:

let numbers = [1, 2, 2, 3, 4, 4];
let unique = [...new Set(numbers)];  // [1, 2, 3, 4]

 

Ưu điểm: Đơn giản, nhanh và tích hợp sẵn.


Nhược điểm: Không hoạt động với các đối tượng (sử dụng map() cho trường hợp đó).

 

7. Làm phẳng các mảng lồng nhau

 

Sử dụng flat()


Phương thức flat() làm phẳng các mảng lồng nhau đến độ sâu được chỉ định.

 

Ví dụ:

let nested = [1, [2, 3], [4, [5, 6]]];
let flatArr = nested.flat(2);  // [1, 2, 3, 4, 5, 6]

 

Ưu điểm: Giảm độ phức tạp khi xử lý các mảng lồng nhau sâu.


Nhược điểm: Chỉ hoạt động trên các trình duyệt hiện đại.

 

8. Sắp xếp mảng

 

Sử dụng sort() (cẩn thận)


Theo mặc định, sort() chuyển đổi các phần tử thành chuỗi trước khi sắp xếp, điều này có thể gây ra sự cố.

 

Ví dụ:

let numbers = [3, 1, 10, 5];
numbers.sort((a, b) => a - b); // [1, 3, 5, 10] (Tăng dần)

 

Ưu điểm: Linh hoạt để sắp xếp mảng theo bất kỳ thứ tự nào.


Nhược điểm: Nếu không có hàm so sánh, nó sẽ sắp xếp theo từ điển, điều này có thể không mong muốn.

 

Trường hợp biên cho sort()

// Ví dụ: trường hợp biên cho sort()
let mixedArray = [undefined, 1, 10, null, 5, 'a'];
mixedArray.sort((a,b) => {
    if (a === undefined) return 1;
    if (b === undefined) return -1;
    if (a === null) return 1;
    if (b === null) return -1;
    if (typeof a === 'string') return 1;
    if (typeof b === 'string') return -1;
    return a - b;
});
console.log(mixedArray);

 

9. Chuyển đổi chuỗi thành mảng

 

Sử dụng split()


Một trường hợp sử dụng phổ biến là chia một chuỗi thành một mảng.

 

Ví dụ:

let str = "hello world";
let words = str.split(" ");  // ["hello", "world"]

 

Ưu điểm: Hữu ích để phân tích và thao tác văn bản.


Nhược điểm: Yêu cầu một dấu phân cách và không xử lý tốt nhiều khoảng trắng.

 

Suy nghĩ cuối cùng


JavaScript mảng rất mạnh mẽ và linh hoạt. Bằng cách nắm vững những mẹo này, bạn có thể viết mã sạch hơn và hiệu quả hơn. 

Liên hệ với chúng tôi nếu bạn gặp sự cố/câu hỏi

Tag list:
- JavaScript map filter reduce
- JavaScript best practices
- JavaScript array methods
- How to use arrays in JavaScript
- JavaScript functional programming
- JavaScript array tips
- JavaScript array push and pop
- JavaScript arrays
- Sorting arrays in JavaScript
- Removing duplicates in JavaScript

Liên quan

Javascript Tools

Đọc thêm
Python Unit Test

Đọc thêm
Python Flask

Đọc thêm

Theo dõi

Theo dõi bản tin của chúng tôi và không bao giờ bỏ lỡ những tin tức mới nhất.