Cách sử dụng Mảng (Arrays) trong JavaScript

Javascript căn bản | by Học Javascript

Trong lập trình JavaScript, mảng (array) là một cấu trúc dữ liệu quan trọng giúp lưu trữ và quản lý danh sách các phần tử một cách hiệu quả. Mảng cho phép chúng ta thực hiện nhiều thao tác như thêm, xóa, sắp xếp và duyệt qua các phần tử một cách dễ dàng. Nhờ vào các phương thức mạnh mẽ và tính linh hoạt, mảng được sử dụng rộng rãi trong hầu hết các ứng dụng JavaScript, từ xử lý dữ liệu đến xây dựng giao diện web. Bài viết này sẽ giúp bạn hiểu rõ cách khai báo, truy cập và sử dụng mảng một cách hiệu quả trong JavaScript.

Mảng trong JavaScript là gì?

Mảng (Array) trong JavaScript là một cấu trúc dữ liệu dùng để lưu trữ nhiều giá trị trong một biến duy nhất. Các phần tử trong mảng được sắp xếp theo chỉ mục (index), bắt đầu từ 0. Điều này giúp dễ dàng truy xuất và quản lý dữ liệu hơn so với việc sử dụng nhiều biến riêng lẻ.

Ví dụ về mảng:

let numbers = [1, 2, 3, 4, 5];  // Mảng chứa các số
let fruits = ["Táo", "Chuối", "Cam"];  // Mảng chứa chuỗi
let mixedArray = [10, "Hello", true, null];  // Mảng chứa nhiều kiểu dữ liệu

Đặc điểm của mảng

  • Mảng có thể chứa nhiều kiểu dữ liệu khác nhau: Không giống như một số ngôn ngữ lập trình khác (như Java hay C++), JavaScript cho phép một mảng chứa các phần tử có kiểu dữ liệu khác nhau.
  • Chỉ mục bắt đầu từ 0: Phần tử đầu tiên có chỉ mục là 0, phần tử thứ hai là 1, và cứ tiếp tục như vậy.
  • Độ dài động (Dynamic Size): Mảng trong JavaScript có thể thay đổi kích thước một cách linh hoạt, nghĩa là bạn có thể thêm hoặc xóa phần tử mà không cần khai báo trước số lượng phần tử cố định.
  • Là một đối tượng kiểu Object: Mặc dù mảng có cú pháp riêng biệt, về bản chất, nó là một đối tượng trong JavaScript với các chỉ mục số làm thuộc tính.

Ví dụ kiểm tra kiểu dữ liệu của mảng:

let arr = [1, 2, 3];
console.log(typeof arr); // Kết quả: "object"
console.log(Array.isArray(arr)); // Kết quả: true (Kiểm tra có phải mảng hay không)

Khai báo mảng

Có hai cách phổ biến để khai báo mảng trong JavaScript:

Sử dụng dấu [] (Array Literal - Cách phổ biến nhất)

Cách này đơn giản và dễ hiểu, thường được sử dụng trong hầu hết các trường hợp:

let emptyArray = [];  // Mảng rỗng
let numbers = [1, 2, 3, 4, 5];  // Mảng số
let colors = ["Đỏ", "Xanh", "Vàng"];  // Mảng chuỗi

Sử dụng từ khóa new Array()

Cách này ít được sử dụng hơn do có một số nhược điểm, chẳng hạn như nếu truyền một số duy nhất, nó sẽ tạo mảng có kích thước tương ứng thay vì một phần tử duy nhất.

let arr1 = new Array();  // Mảng rỗng
let arr2 = new Array(5);  // Mảng có độ dài 5 nhưng không có phần tử
let arr3 = new Array(1, 2, 3);  // Mảng chứa 3 phần tử: [1, 2, 3]

console.log(arr2.length); // Kết quả: 5
console.log(arr3); // Kết quả: [1, 2, 3]

Lưu ý:

  • Khi dùng new Array(5), mảng sẽ có độ dài là 5 nhưng chưa có giá trị trong các phần tử.
  • Khi dùng new Array(1, 2, 3), nó sẽ tạo một mảng bình thường với các phần tử [1, 2, 3].

Khuyến nghị: Sử dụng cú pháp [] để khai báo mảng thay vì new Array() để tránh lỗi không mong muốn.

Cách tạo và truy cập phần tử mảng trong JavaScript

Khai báo mảng bằng [] và new Array()

Sử dụng dấu [] (Array Literal - Cách phổ biến nhất)

Đây là cách đơn giản và được khuyến nghị sử dụng vì tính trực quan và dễ hiểu.

let numbers = [1, 2, 3, 4, 5];  // Mảng chứa số
let fruits = ["Táo", "Chuối", "Cam"];  // Mảng chứa chuỗi
let mixedArray = [10, "Hello", true, null];  // Mảng chứa nhiều kiểu dữ liệu khác nhau
let emptyArray = [];  // Mảng rỗng

Sử dụng new Array()

Cách này ít được sử dụng hơn do có thể gây nhầm lẫn.

let arr1 = new Array();  // Tạo một mảng rỗng
let arr2 = new Array(5);  // Tạo một mảng có độ dài 5 nhưng không có giá trị trong các phần tử
let arr3 = new Array(1, 2, 3, 4);  // Tạo một mảng chứa các phần tử [1, 2, 3, 4]

Lưu ý:

  • Khi gọi new Array(5), mảng sẽ có độ dài 5 nhưng các phần tử đều là undefined.
  • Khi gọi new Array(1, 2, 3), nó tạo một mảng bình thường với các phần tử [1, 2, 3].

Khuyến nghị: Nên sử dụng [] để khai báo mảng thay vì new Array() để tránh lỗi không mong muốn.

Truy cập phần tử theo chỉ mục (index)

Mỗi phần tử trong mảng có một chỉ mục (index), bắt đầu từ 0 đến length - 1.

Truy cập phần tử

Sử dụng cú pháp array[index]:

let fruits = ["Táo", "Chuối", "Cam"];
console.log(fruits[0]); // Kết quả: "Táo"
console.log(fruits[1]); // Kết quả: "Chuối"
console.log(fruits[2]); // Kết quả: "Cam"

Nếu truy cập một phần tử ngoài phạm vi:

console.log(fruits[5]); // Kết quả: undefined (Không có phần tử tại index 5)

Thay đổi giá trị phần tử

Có thể gán giá trị mới cho một phần tử trong mảng:

let numbers = [10, 20, 30];
numbers[1] = 50;  // Thay đổi giá trị tại index 1
console.log(numbers); // Kết quả: [10, 50, 30]

Truy cập phần tử cuối cùng

Dùng array.length - 1 để truy cập phần tử cuối cùng:

let colors = ["Đỏ", "Xanh", "Vàng"];
console.log(colors[colors.length - 1]); // Kết quả: "Vàng"

Duyệt mảng bằng vòng lặp (for, forEach, map)

Dùng vòng lặp for (Cách truyền thống)

let numbers = [1, 2, 3, 4, 5];

for (let i = 0; i < numbers.length; i++) {
    console.log(numbers[i]); 
}
// Kết quả: 1, 2, 3, 4, 5

Ưu điểm: Cho phép truy cập chỉ mục (i) và có thể dễ dàng thay đổi phần tử trong mảng.

Dùng vòng lặp forEach()

forEach() giúp duyệt từng phần tử mà không cần chỉ mục.

let fruits = ["Táo", "Chuối", "Cam"];

fruits.forEach(function(fruit, index) {
    console.log(`Phần tử ${index}: ${fruit}`);
});
// Kết quả:
// Phần tử 0: Táo
// Phần tử 1: Chuối
// Phần tử 2: Cam

Ưu điểm: Ngắn gọn, dễ đọc, không cần thao tác thủ công với index.

Dùng vòng lặp map() (Tạo mảng mới từ mảng cũ)

Khác với forEach(), map() không chỉ duyệt mà còn tạo một mảng mới từ kết quả trả về của callback function.

let numbers = [1, 2, 3, 4, 5];
let doubledNumbers = numbers.map(num => num * 2);

console.log(doubledNumbers); 
// Kết quả: [2, 4, 6, 8, 10]

Ưu điểm: Trả về một mảng mới mà không làm thay đổi mảng ban đầu.

Dùng forEach() hoặc map() thay vì for nếu không cần thay đổi giá trị phần tử trong mảng.

Các phương thức thao tác với mảng trong JavaScript

Thêm, xóa phần tử

Thêm phần tử

push() – Thêm phần tử vào cuối mảng

let fruits = ["Táo", "Chuối"];
fruits.push("Cam");  
console.log(fruits);  // Kết quả: ["Táo", "Chuối", "Cam"]

Trả về: Độ dài mới của mảng.

unshift() – Thêm phần tử vào đầu mảng

let numbers = [2, 3, 4];
numbers.unshift(1);  
console.log(numbers);  // Kết quả: [1, 2, 3, 4]
Trả về: Độ dài mới của mảng.

Xóa phần tử

pop() – Xóa phần tử cuối cùng

let fruits = ["Táo", "Chuối", "Cam"];
let lastFruit = fruits.pop();  
console.log(fruits);  // Kết quả: ["Táo", "Chuối"]
console.log(lastFruit);  // Kết quả: "Cam"

Trả về: Phần tử bị xóa.

shift() – Xóa phần tử đầu tiên

let numbers = [1, 2, 3, 4];
let firstNumber = numbers.shift();  
console.log(numbers);  // Kết quả: [2, 3, 4]
console.log(firstNumber);  // Kết quả: 1
Trả về: Phần tử bị xóa.

splice() – Xóa, thêm, hoặc thay thế phần tử

  • Xóa phần tử
let fruits = ["Táo", "Chuối", "Cam", "Dưa"];
fruits.splice(1, 2);  
console.log(fruits);  // Kết quả: ["Táo", "Dưa"]

Giải thích: Xóa 2 phần tử bắt đầu từ vị trí 1.

  • Thêm phần tử
let colors = ["Đỏ", "Xanh"];
colors.splice(1, 0, "Vàng", "Tím");  
console.log(colors);  // Kết quả: ["Đỏ", "Vàng", "Tím", "Xanh"]

Giải thích: Thêm "Vàng""Tím" vào vị trí 1, không xóa phần tử nào.

  • Thay thế phần tử
let animals = ["Chó", "Mèo", "Cá"];
animals.splice(1, 1, "Voi");  
console.log(animals);  // Kết quả: ["Chó", "Voi", "Cá"]

Giải thích: Thay "Mèo" bằng "Voi" (xóa 1 phần tử ở vị trí 1 và thêm "Voi").

Duyệt và xử lý mảng

forEach() – Lặp qua từng phần tử

let numbers = [1, 2, 3, 4];
numbers.forEach(num => console.log(num * 2));
// Kết quả: 2, 4, 6, 8

Không trả về mảng mới.

map() – Tạo mảng mới từ mảng gốc

let numbers = [1, 2, 3, 4];
let doubled = numbers.map(num => num * 2);
console.log(doubled);  // Kết quả: [2, 4, 6, 8]

Trả về mảng mới.

filter() – Lọc phần tử theo điều kiện

let numbers = [1, 2, 3, 4, 5];
let evenNumbers = numbers.filter(num => num % 2 === 0);
console.log(evenNumbers);  // Kết quả: [2, 4]

Trả về mảng mới chứa các phần tử thỏa điều kiện.

reduce() – Tính toán giá trị duy nhất từ mảng

let numbers = [1, 2, 3, 4, 5];
let sum = numbers.reduce((acc, num) => acc + num, 0);
console.log(sum);  // Kết quả: 15

Trả về một giá trị duy nhất.

find() – Tìm phần tử đầu tiên thỏa điều kiện

let numbers = [10, 20, 30, 40];
let found = numbers.find(num => num > 15);
console.log(found);  // Kết quả: 20

Trả về phần tử đầu tiên tìm thấy.

findIndex() – Tìm vị trí phần tử đầu tiên thỏa điều kiện

let index = numbers.findIndex(num => num > 15);
console.log(index);  // Kết quả: 1

Trả về chỉ mục của phần tử đầu tiên tìm thấy.

some() – Kiểm tra xem có phần tử nào thỏa điều kiện không

let numbers = [10, 20, 30];
let hasLargeNumber = numbers.some(num => num > 25);
console.log(hasLargeNumber);  // Kết quả: true

Trả về true nếu tất cả phần tử thỏa điều kiện.

Sắp xếp và đảo ngược mảng

sort() – Sắp xếp mảng

let numbers = [5, 2, 9, 1, 3];
numbers.sort((a, b) => a - b);  
console.log(numbers);  // Kết quả: [1, 2, 3, 5, 9]

Sắp xếp theo thứ tự tăng dần.

reverse() – Đảo ngược mảng

let letters = ["a", "b", "c"];
letters.reverse();
console.log(letters);  // Kết quả: ["c", "b", "a"]

Kết hợp mảng

concat() – Nối nhiều mảng

let arr1 = [1, 2];
let arr2 = [3, 4];
let combined = arr1.concat(arr2);
console.log(combined);  // Kết quả: [1, 2, 3, 4]
Spread Operator (...)
let arr1 = [1, 2];
let arr2 = [3, 4];
let combined = [...arr1, ...arr2];
console.log(combined);  // Kết quả: [1, 2, 3, 4]

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

join() – Nối các phần tử thành chuỗi

let words = ["Hello", "world"];
console.log(words.join(" "));  // Kết quả: "Hello world"
toString() – Chuyển mảng thành chuỗi
let numbers = [1, 2, 3];
console.log(numbers.toString());  // Kết quả: "1,2,3"

Mảng đa chiều (Multidimensional Arrays) trong JavaScript

Khái niệm mảng nhiều chiều

Mảng đa chiều trong JavaScript là mảng chứa các mảng con bên trong, cho phép tổ chức dữ liệu dưới dạng bảng hoặc ma trận. Mảng 2 chiều (mảng của mảng) là dạng phổ biến nhất, thường được sử dụng để biểu diễn bảng dữ liệu, lưới ô vuông hoặc các cấu trúc dữ liệu phức tạp hơn.

Ví dụ về mảng hai chiều:

let matrix = [
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9]
];

Ở đây, matrix có 3 hàng, mỗi hàng là một mảng con chứa 3 phần tử.

Cách tạo và truy cập mảng nhiều chiều

Tạo mảng đa chiều

  • Dùng cú pháp mảng lồng nhau
let array2D = [
    ["a", "b", "c"],
    ["d", "e", "f"],
    ["g", "h", "i"]
];
Tạo động bằng vòng lặp
let rows = 3, cols = 3;
let dynamicArray = new Array(rows).fill().map(() => new Array(cols).fill(0));
console.log(dynamicArray);
// Kết quả: [[0, 0, 0], [0, 0, 0], [0, 0, 0]]

Truy cập phần tử trong mảng nhiều chiều
Phần tử được truy cập bằng cách sử dụng chỉ mục của hàng và cột.

console.log(array2D[0][1]);  // Kết quả: "b"
console.log(array2D[2][2]);  // Kết quả: "i"

Lưu ý: Chỉ mục bắt đầu từ 0.

Duyệt mảng nhiều chiều bằng vòng lặp

for (let i = 0; i < array2D.length; i++) {
    for (let j = 0; j < array2D[i].length; j++) {
        console.log(array2D[i][j]);
    }
}
Hoặc sử dụng forEach()
array2D.forEach(row => row.forEach(cell => console.log(cell)));
Thêm phần tử vào mảng nhiều chiều
array2D[1].push("x");
console.log(array2D[1]);  // Kết quả: ["d", "e", "f", "x"]

Xóa phần tử

array2D[1].pop();
console.log(array2D[1]);  // Kết quả: ["d", "e", "f"]

Mảng đa chiều hơn 2 cấp

let array3D = [
    [
        [1, 2], 
        [3, 4]
    ],
    [
        [5, 6], 
        [7, 8]
    ]
];
console.log(array3D[1][0][1]);  // Kết quả: 6

Các lưu ý khi làm việc với mảng trong JavaScript

Mảng có thể chứa nhiều kiểu dữ liệu khác nhau

Trong JavaScript, mảng có thể chứa các kiểu dữ liệu khác nhau như số, chuỗi, đối tượng, hoặc thậm chí là các hàm.

let mixedArray = [1, "Hello", true, { name: "John" }, [1, 2, 3], function() { return "Hi"; }];
console.log(mixedArray[3].name);  // Kết quả: "John"
console.log(mixedArray[5]());     // Kết quả: "Hi"

Lưu ý: Điều này có thể dẫn đến lỗi nếu không kiểm tra kỹ kiểu dữ liệu trước khi thao tác.

Sự khác biệt giữa mảng và đối tượng

Đặc điểm Mảng (Array) Đối tượng (Object)
Cách truy cập Dùng chỉ mục (arr[0]) Dùng key (obj.name)
Thứ tự phần tử Có thứ tự Không có thứ tự
Tính năng Các phương thức như map(), filter() Không có sẵn các phương thức này

Ví dụ về đối tượng:

let person = {
    name: "Alice",
    age: 25
};
console.log(person.name);  // Kết quả: "Alice"

Ví dụ về mảng:

let people = ["Alice", "Bob", "Charlie"];
console.log(people[0]);  // Kết quả: "Alice"

Hiệu suất khi thao tác với mảng lớn

Lưu ý về hiệu suất

  • Tránh sử dụng splice() trong vòng lặp, vì nó ảnh hưởng đến hiệu suất do phải thay đổi chỉ mục của phần tử còn lại.
  • Sử dụng map(), filter(), reduce() thay vì forEach() nếu cần một mảng mới.
  • Hạn chế việc thêm/xóa phần tử đầu mảng (shift(), unshift()), vì nó làm thay đổi chỉ mục của tất cả phần tử sau.

Sử dụng Set thay vì mảng nếu cần tìm kiếm nhanh

let numArray = [1, 2, 3, 4, 5, 6];
console.log(numArray.includes(4));  // O(n)

let numSet = new Set(numArray);
console.log(numSet.has(4));  // O(1)

Set tìm kiếm nhanh hơn khi làm việc với tập hợp lớn.

Sử dụng TypedArray nếu cần hiệu suất cao

let buffer = new ArrayBuffer(16);
let intArray = new Int32Array(buffer);
console.log(intArray);  // Int32Array(4) [0, 0, 0, 0]

TypedArray giúp tối ưu bộ nhớ và tốc độ xử lý dữ liệu số.

Kết bài

Mảng (Arrays) là một trong những cấu trúc dữ liệu quan trọng và được sử dụng rộng rãi trong JavaScript. Việc hiểu rõ cách khai báo, truy cập, duyệt và thao tác với mảng giúp lập trình viên làm việc hiệu quả hơn khi xử lý dữ liệu.

Bên cạnh đó, việc nắm vững các phương thức thao tác trên mảng như map(), filter(), reduce(), hay các kỹ thuật tối ưu hiệu suất khi làm việc với mảng lớn là rất cần thiết để viết mã nguồn tối ưu và nâng cao hiệu suất ứng dụng.

Hy vọng bài viết này giúp bạn có cái nhìn rõ ràng hơn về mảng trong JavaScript. Hãy tiếp tục thực hành và khám phá các tính năng nâng cao để làm chủ cấu trúc dữ liệu này trong các dự án thực tế!

Bài viết liên quan

  • 2