Mảng
Trong bài học này, chúng ta sẽ xem xét mảng — một cách gọn gàng để lưu trữ danh sách các mục dữ liệu dưới một tên biến duy nhất. Ở đây, chúng ta xem xét lý do tại sao điều này hữu ích, sau đó khám phá cách tạo mảng, truy xuất, thêm và xóa các mục được lưu trữ trong mảng, và nhiều hơn nữa.
| Điều kiện tiên quyết: | Hiểu biết về HTML và các nguyên tắc cơ bản của CSS. Quen thuộc với các kiểu dữ liệu cơ bản như số và chuỗi, như đã đề cập trong các bài học trước. |
|---|---|
| Kết quả học tập: |
|
Mảng là gì?
Mảng thường được mô tả là "các đối tượng giống danh sách"; về cơ bản, chúng là các đối tượng đơn chứa nhiều giá trị được lưu trữ trong một danh sách. Các đối tượng mảng có thể được lưu trữ trong các biến và xử lý theo cách gần như giống với bất kỳ loại giá trị nào khác, sự khác biệt là chúng ta có thể truy cập từng giá trị bên trong danh sách riêng lẻ và làm những điều siêu hữu ích và hiệu quả với danh sách, như lặp qua nó và làm cùng một thứ với mọi giá trị. Có thể chúng ta có một loạt các mục sản phẩm và giá của chúng được lưu trữ trong một mảng, và chúng ta muốn lặp qua tất cả chúng và in chúng trên hóa đơn, đồng thời cộng tất cả giá lại với nhau và in ra tổng giá ở cuối.
Nếu chúng ta không có mảng, chúng ta sẽ phải lưu trữ mọi mục trong một biến riêng biệt, sau đó gọi mã thực hiện việc in và thêm riêng biệt cho mỗi mục. Điều này sẽ lâu hơn nhiều để viết ra, kém hiệu quả hơn và dễ mắc lỗi hơn. Nếu chúng ta có 10 mục cần thêm vào hóa đơn thì đã khó chịu rồi, nhưng nếu là 100 mục, hoặc 1000 mục thì sao? Chúng ta sẽ trở lại ví dụ này sau trong bài.
Như trong các bài trước, hãy tìm hiểu về những điều cơ bản thực sự của mảng bằng cách nhập một số ví dụ vào bảng điều khiển (console) nhà phát triển trình duyệt.
Note: Scrimba's Aside: Intro to arrays scrim MDN learning partner cung cấp phần giới thiệu tương tác hữu ích về mảng với các ví dụ và thử thách để kiểm tra kiến thức của bạn.
Tạo mảng
Mảng bao gồm dấu ngoặc vuông và các mục được phân tách bằng dấu phẩy.
-
Giả sử chúng ta muốn lưu trữ một danh sách mua sắm trong một mảng. Dán mã sau vào bảng điều khiển (console):
jsconst shopping = ["bread", "milk", "cheese", "hummus", "noodles"]; console.log(shopping); -
Trong ví dụ trên, mỗi mục là một chuỗi, nhưng trong mảng, chúng ta có thể lưu trữ nhiều kiểu dữ liệu khác nhau — chuỗi, số, đối tượng và thậm chí các mảng khác. Chúng ta cũng có thể trộn các kiểu dữ liệu trong một mảng — chúng ta không phải giới hạn bản thân chỉ lưu số trong một mảng, và trong mảng khác chỉ lưu chuỗi. Ví dụ:
jsconst sequence = [1, 1, 2, 3, 5, 8, 13]; const random = ["tree", 795, [0, 1, 2]]; -
Trước khi tiếp tục, hãy tạo một vài mảng ví dụ.
Tìm độ dài của mảng
Bạn có thể tìm ra độ dài của mảng (có bao nhiêu mục trong đó) theo đúng cách giống như bạn tìm ra độ dài (tính bằng ký tự) của chuỗi — bằng cách sử dụng thuộc tính length. Hãy thử đoạn sau:
const shopping = ["bread", "milk", "cheese", "hummus", "noodles"];
console.log(shopping.length); // 5
Truy cập và sửa đổi các mục mảng
Mảng là bộ sưu tập được lập chỉ số. Các mục trong mảng được đánh số, bắt đầu từ không. Con số này được gọi là chỉ số của mục. Vì vậy, mục đầu tiên có chỉ số 0, mục thứ hai có chỉ số 1, v.v. Bạn có thể truy cập các mục riêng lẻ trong mảng bằng ký hiệu dấu ngoặc và cung cấp chỉ số của mục, theo cách tương tự như bạn truy cập các chữ cái trong chuỗi.
-
Nhập vào bảng điều khiển (console) của bạn:
jsconst shopping = ["bread", "milk", "cheese", "hummus", "noodles"]; console.log(shopping[0]); // returns "bread" -
Bạn cũng có thể sửa đổi một mục trong mảng bằng cách đặt cho một mục mảng đơn một giá trị mới. Hãy thử điều này:
jsconst shopping = ["bread", "milk", "cheese", "hummus", "noodles"]; shopping[0] = "tahini"; console.log(shopping); // shopping will now return [ "tahini", "milk", "cheese", "hummus", "noodles" ]Note: Chúng ta đã nói điều này trước đó, nhưng chỉ nhắc nhở — JavaScript bắt đầu lập chỉ số mảng từ không!
-
Lưu ý rằng mảng bên trong mảng được gọi là mảng đa chiều. Bạn có thể truy cập một mục bên trong mảng là chính nó bên trong mảng khác bằng cách kết hợp hai bộ dấu ngoặc vuông lại với nhau. Ví dụ, để truy cập một trong các mục bên trong mảng là mục thứ ba bên trong mảng
random(xem phần trước), chúng ta có thể làm điều gì đó như thế này:jsconst random = ["tree", 795, [0, 1, 2]]; random[2][2]; -
Hãy thử thực hiện một số sửa đổi nữa cho các ví dụ mảng của bạn trước khi tiếp tục. Chơi một chút, và xem những gì hoạt động và những gì không.
Tìm chỉ số của các mục trong mảng
Nếu bạn không biết chỉ số của một mục, bạn có thể sử dụng phương thức indexOf().
Phương thức indexOf() lấy một mục làm đối số và sẽ trả về chỉ số của mục hoặc -1 nếu mục không có trong mảng:
const birds = ["Parrot", "Falcon", "Owl"];
console.log(birds.indexOf("Owl")); // 2
console.log(birds.indexOf("Rabbit")); // -1
Thêm các mục
Để thêm một hoặc nhiều mục vào cuối mảng, chúng ta có thể sử dụng push(). Lưu ý rằng bạn cần bao gồm một hoặc nhiều mục mà bạn muốn thêm vào cuối mảng.
const cities = ["Manchester", "Liverpool"];
cities.push("Cardiff");
console.log(cities); // [ "Manchester", "Liverpool", "Cardiff" ]
cities.push("Bradford", "Brighton");
console.log(cities); // [ "Manchester", "Liverpool", "Cardiff", "Bradford", "Brighton" ]
Độ dài mới của mảng được trả về khi lời gọi phương thức hoàn thành. Nếu bạn muốn lưu trữ độ dài mảng mới trong một biến, bạn có thể làm điều gì đó như thế này:
const cities = ["Manchester", "Liverpool"];
const newLength = cities.push("Bristol");
console.log(cities); // [ "Manchester", "Liverpool", "Bristol" ]
console.log(newLength); // 3
Để thêm một mục vào đầu mảng, hãy sử dụng unshift():
const cities = ["Manchester", "Liverpool"];
cities.unshift("Edinburgh");
console.log(cities); // [ "Edinburgh", "Manchester", "Liverpool" ]
Xóa các mục
Để xóa mục cuối cùng khỏi mảng, hãy sử dụng pop().
const cities = ["Manchester", "Liverpool"];
cities.pop();
console.log(cities); // [ "Manchester" ]
Phương thức pop() trả về mục đã được xóa. Để lưu mục đó trong một biến mới, bạn có thể làm điều này:
const cities = ["Manchester", "Liverpool"];
const removedCity = cities.pop();
console.log(removedCity); // "Liverpool"
Để xóa mục đầu tiên khỏi mảng, hãy sử dụng shift():
const cities = ["Manchester", "Liverpool"];
cities.shift();
console.log(cities); // [ "Liverpool" ]
Nếu bạn biết chỉ số của một mục, bạn có thể xóa nó khỏi mảng bằng splice():
const cities = ["Manchester", "Liverpool", "Edinburgh", "Carlisle"];
const index = cities.indexOf("Liverpool");
if (index !== -1) {
cities.splice(index, 1);
}
console.log(cities); // [ "Manchester", "Edinburgh", "Carlisle" ]
Trong lời gọi splice() này, đối số đầu tiên nói bắt đầu xóa mục từ đâu, và đối số thứ hai nói bao nhiêu mục nên được xóa. Vì vậy, bạn có thể xóa nhiều hơn một mục:
const cities = ["Manchester", "Liverpool", "Edinburgh", "Carlisle"];
const index = cities.indexOf("Liverpool");
if (index !== -1) {
cities.splice(index, 2);
}
console.log(cities); // [ "Manchester", "Carlisle" ]
Truy cập mọi mục
Rất thường xuyên bạn sẽ muốn truy cập mọi mục trong mảng. Bạn có thể làm điều này bằng cách sử dụng câu lệnh for...of:
const birds = ["Parrot", "Falcon", "Owl"];
for (const bird of birds) {
console.log(bird);
}
Đôi khi bạn sẽ muốn làm cùng một thứ với mỗi mục trong mảng, để lại cho bạn một mảng chứa các mục đã được thay đổi. Bạn có thể làm điều này bằng map(). Mã dưới đây lấy một mảng các số và nhân đôi mỗi số:
function double(number) {
return number * 2;
}
const numbers = [5, 2, 7, 6];
const doubled = numbers.map(double);
console.log(doubled); // [ 10, 4, 14, 12 ]
Chúng ta đưa một hàm vào map(), và map() gọi hàm một lần cho mỗi mục trong mảng, truyền mục vào. Sau đó nó thêm giá trị trả về từ mỗi lời gọi hàm vào một mảng mới, và cuối cùng trả về mảng mới.
Đôi khi bạn sẽ muốn tạo một mảng mới chỉ chứa các mục trong mảng gốc khớp với một số bài kiểm tra. Bạn có thể làm điều đó bằng filter(). Mã dưới đây lấy một mảng chuỗi và trả về một mảng chỉ chứa các chuỗi dài hơn 8 ký tự:
function isLong(city) {
return city.length > 8;
}
const cities = ["London", "Liverpool", "Totnes", "Edinburgh"];
const longer = cities.filter(isLong);
console.log(longer); // [ "Liverpool", "Edinburgh" ]
Giống như map(), chúng ta đưa một hàm vào phương thức filter(), và filter() gọi hàm này cho mọi mục trong mảng, truyền mục vào. Nếu hàm trả về true, thì mục được thêm vào một mảng mới. Cuối cùng nó trả về mảng mới.
Chuyển đổi giữa chuỗi và mảng
Thường bạn sẽ được trình bày với một số dữ liệu thô chứa trong một chuỗi dài, và bạn có thể muốn tách các mục hữu ích ra thành một dạng hữu ích hơn và sau đó làm những điều với chúng, như hiển thị chúng trong bảng dữ liệu. Để làm điều này, chúng ta có thể sử dụng phương thức split(). Trong dạng đơn giản nhất, nó lấy một tham số duy nhất, ký tự bạn muốn tách chuỗi tại đó, và trả về các chuỗi con giữa dấu phân cách như các mục trong mảng.
Note: Được rồi, đây về mặt kỹ thuật là phương thức chuỗi, không phải phương thức mảng, nhưng chúng ta đã đặt nó với mảng vì nó phù hợp ở đây.
-
Hãy chơi với điều này để xem cách hoạt động. Trước tiên, hãy tạo một chuỗi trong bảng điều khiển (console) của bạn:
jsconst data = "Manchester,London,Liverpool,Birmingham,Leeds,Carlisle"; -
Bây giờ hãy tách nó tại mỗi dấu phẩy:
jsconst cities = data.split(","); cities; -
Cuối cùng, hãy thử tìm độ dài của mảng mới và truy xuất một số mục từ nó:
jscities.length; cities[0]; // the first item in the array cities[1]; // the second item in the array cities[cities.length - 1]; // the last item in the array -
Bạn cũng có thể đi theo chiều ngược lại bằng phương thức
join(). Hãy thử đoạn sau:jsconst commaSeparated = cities.join(","); commaSeparated; -
Một cách khác để chuyển đổi mảng thành chuỗi là sử dụng phương thức
toString().toString()có thể đơn giản hơnjoin()vì nó không lấy tham số, nhưng hạn chế hơn. Vớijoin()bạn có thể chỉ định các dấu phân cách khác nhau, trong khitoString()luôn sử dụng dấu phẩy. (Hãy thử chạy Bước 4 với một ký tự khác dấu phẩy.)jsconst dogNames = ["Rocket", "Flash", "Bella", "Slugger"]; dogNames.toString(); // Rocket,Flash,Bella,Slugger
In những sản phẩm đó
Đến lượt bạn. Trong bài tập này, bạn sẽ trở lại ví dụ chúng ta đã mô tả trước đó — in tên và giá sản phẩm trên hóa đơn, sau đó cộng tổng giá và in chúng ở cuối. Làm theo các bước dưới đây để triển khai logic.
- Nhấp "Play" trong khối mã bên dưới để chỉnh sửa ví dụ trong MDN Playground.
- Bên dưới nhận xét
// Part 1là một số chuỗi, mỗi chuỗi chứa tên sản phẩm và giá được phân tách bằng dấu hai chấm. Chúng ta muốn bạn bỏ ghi chú những chuỗi này và biến chúng thành mảng có tênproducts. - Bên dưới nhận xét
// Part 2, hãy bắt đầu vòng lặpfor...of()để đi qua mọi mục trong mảngproducts. - Bên dưới nhận xét
// Part 3, chúng ta muốn bạn viết một dòng mã tách mục mảng hiện tại (name:price) thành hai mục riêng biệt, một chứa tên và một chứa giá. Nếu bạn không chắc cách làm điều này, hãy xem bài Phương thức chuỗi hữu ích để được giúp đỡ, hoặc tốt hơn, hãy xem phần Chuyển đổi giữa chuỗi và mảng của bài này. - Là một phần của dòng mã trên, bạn cũng sẽ muốn chuyển đổi giá từ chuỗi thành số. Nếu bạn không thể nhớ cách làm điều này, hãy xem bài chuỗi đầu tiên.
- Có một biến gọi là
totalđược tạo ra và được đặt giá trị là0ở đầu mã. Bên trong vòng lặp (bên dưới// Part 4), chúng ta muốn bạn thêm một dòng cộng giá mục hiện tại vào tổng đó trong mỗi lần lặp của vòng lặp, để ở cuối mã tổng đúng được in trên hóa đơn. Bạn có thể cần toán tử gán để làm điều này. - Chúng ta muốn bạn thay đổi dòng tiếp theo sau
// Part 5để biếnitemTextđược đặt bằng "tên mục hiện tại — $giá mục hiện tại", ví dụ "Shoes — $23.99" trong mỗi trường hợp, để thông tin đúng cho mỗi mục được in trên hóa đơn. Đây là nối chuỗi cơ bản, mà bạn đã quen thuộc nếu bạn đã làm theo tài liệu học cho đến nay. - Cuối cùng, bên dưới nhận xét
// Part 6, bạn cần thêm một}để đánh dấu kết thúc của vòng lặpfor...of().
Nếu bạn mắc lỗi, bạn có thể xóa công việc của mình bằng nút Reset trong MDN Playground. Nếu bạn thực sự bị kẹt, bạn có thể xem giải pháp bên dưới đầu ra trực tiếp.
const list = document.querySelector(".output ul");
const totalBox = document.querySelector(".output p");
let total = 0;
list.textContent = "";
totalBox.textContent = "";
// Part 1
// "Underpants:6.99",
// "Socks:5.99",
// "T-shirt:14.99",
// "Trousers:31.99",
// "Shoes:23.99",
// Part 2
// Part 3
// Part 4
// Part 5
let itemText = 0;
const listItem = document.createElement("li");
listItem.textContent = itemText;
list.appendChild(listItem);
// Part 6
totalBox.textContent = `Total: $${total.toFixed(2)}`;
Nhấp vào đây để xem giải pháp
JavaScript hoàn thành của bạn sẽ trông như thế này:
const list = document.querySelector(".output ul");
const totalBox = document.querySelector(".output p");
let total = 0;
list.textContent = "";
totalBox.textContent = "";
const products = [
"Underpants:6.99",
"Socks:5.99",
"T-shirt:14.99",
"Trousers:31.99",
"Shoes:23.99",
];
for (const product of products) {
const subArray = product.split(":");
const name = subArray[0];
const price = Number(subArray[1]);
total += price;
const itemText = `${name} — $${price}`;
const listItem = document.createElement("li");
listItem.textContent = itemText;
list.appendChild(listItem);
}
totalBox.textContent = `Total: $${total.toFixed(2)}`;
Lưu trữ 5 tìm kiếm gần đây
Hãy để bạn hoàn thành một bài tập khác, để tiếp tục luyện tập.
Một cách sử dụng tốt cho các phương thức mảng như push() và pop() là khi bạn đang duy trì hồ sơ các mục hiện đang hoạt động trong một ứng dụng web. Trong cảnh hoạt hình chẳng hạn, bạn có thể có một mảng các đối tượng đại diện cho đồ họa nền hiện đang được hiển thị, và bạn có thể chỉ muốn 50 được hiển thị cùng một lúc, vì lý do hiệu suất hoặc lộn xộn. Khi các đối tượng mới được tạo và thêm vào mảng, các đối tượng cũ hơn có thể bị xóa khỏi mảng để duy trì số lượng mong muốn.
Trong ví dụ này, chúng ta sẽ hiển thị một cách sử dụng đơn giản hơn nhiều — ở đây chúng ta đang cung cấp cho bạn một trang web tìm kiếm giả, với hộp tìm kiếm. Ý tưởng là khi các thuật ngữ được nhập vào hộp tìm kiếm, 5 thuật ngữ tìm kiếm trước đó hàng đầu được hiển thị trong danh sách. Khi số thuật ngữ vượt quá 5, thuật ngữ cuối cùng bắt đầu bị xóa mỗi khi thuật ngữ mới được thêm vào đầu, vì vậy 5 thuật ngữ trước đó luôn được hiển thị.
Note: Trong ứng dụng tìm kiếm thực, bạn có thể nhấp vào các thuật ngữ tìm kiếm trước đó để quay lại các tìm kiếm trước đó, và nó sẽ hiển thị kết quả tìm kiếm thực tế! Chúng ta chỉ đang giữ nó đơn giản cho bây giờ.
Để hoàn thành ví dụ, chúng ta cần bạn:
- Nhấp "Play" trong khối mã bên dưới để chỉnh sửa ví dụ trong MDN Playground.
- Thêm một dòng bên dưới nhận xét
// Part 1để thêm giá trị hiện tại được nhập vào ô nhập tìm kiếm vào đầu mảng. Điều này có thể được lấy bằng cách sử dụngsearchInput.value. - Thêm một dòng bên dưới nhận xét
// Part 2để xóa giá trị hiện tại ở cuối mảng.
Nếu bạn mắc lỗi, bạn có thể xóa công việc của mình bằng nút Reset trong MDN Playground. Nếu bạn thực sự bị kẹt, bạn có thể xem giải pháp bên dưới đầu ra trực tiếp.
const list = document.querySelector(".output ul");
const searchInput = document.querySelector(".output input");
const searchBtn = document.querySelector(".output button");
list.textContent = "";
const myHistory = [];
const MAX_HISTORY = 5;
searchBtn.addEventListener("click", () => {
// we will only allow a term to be entered if the search input isn't empty
if (searchInput.value !== "") {
// Part 1
// empty the list so that we don't display duplicate entries
// the display is regenerated every time a search term is entered.
list.textContent = "";
// loop through the array, and display all the search terms in the list
for (const itemText of myHistory) {
const listItem = document.createElement("li");
listItem.textContent = itemText;
list.appendChild(listItem);
}
// If the array length is 5 or more, remove the oldest search term
if (myHistory.length >= MAX_HISTORY) {
// Part 2
}
// empty the search input and focus it, ready for the next term to be entered
searchInput.value = "";
searchInput.focus();
}
});
Nhấp vào đây để xem giải pháp
JavaScript hoàn thành của bạn sẽ trông như thế này:
const list = document.querySelector(".output ul");
const searchInput = document.querySelector(".output input");
const searchBtn = document.querySelector(".output button");
list.textContent = "";
const myHistory = [];
const MAX_HISTORY = 5;
searchBtn.addEventListener("click", () => {
// we will only allow a term to be entered if the search input isn't empty
if (searchInput.value !== "") {
myHistory.unshift(searchInput.value);
// empty the list so that we don't display duplicate entries
// the display is regenerated every time a search term is entered.
list.textContent = "";
// loop through the array, and display all the search terms in the list
for (const itemText of myHistory) {
const listItem = document.createElement("li");
listItem.textContent = itemText;
list.appendChild(listItem);
}
// If the array length is 5 or more, remove the oldest search term
if (myHistory.length >= MAX_HISTORY) {
myHistory.pop();
}
// empty the search input and focus it, ready for the next term to be entered
searchInput.value = "";
searchInput.focus();
}
});
Tóm tắt
Sau khi đọc qua bài này, chúng ta chắc chắn rằng bạn sẽ đồng ý rằng mảng có vẻ khá hữu ích; bạn sẽ thấy chúng xuất hiện khắp nơi trong JavaScript, thường liên quan đến vòng lặp để làm cùng một thứ với mọi mục trong mảng. Chúng ta sẽ dạy bạn tất cả về vòng lặp sau trong mô-đun.
Trong bài tiếp theo, chúng ta sẽ cung cấp cho bạn một số bài kiểm tra mà bạn có thể sử dụng để kiểm tra mức độ hiểu biết và ghi nhớ thông tin chúng ta đã cung cấp về mảng.
Xem thêm
Array-
Trang tham khảo đối tượng
Arraycung cấp hướng dẫn tham khảo chi tiết về các tính năng được thảo luận trong trang này, và nhiều tính năngArraykhác.