Array – mảng là kiểu dữ liệu phổ biến trong mọi ngôn ngữ lập trình. Bài viết này hưỡng dẫn xử lý Array trong js làm sao để hiệu quả và đúng đắn nhất.
Trong bài viết sẽ hướng dẫn chi tiết các thao tác với mảng trong javascript. Việc này cũng giúp những bạn mới tiếp xúc với js cũng có thể xử lý Array một cách dễ dàng. Nếu bạn là một người có kinh nghiệm lập trình, bài viết này sẽ giúp bạn củng cố thêm kiến thức của mình.
Trong javascript, mảng được khai báo bởi cặp dấu ngoặc vuông [ ], các phần tử cách nhau bới dấu phẩy “,”. Mảng có thể lưu trữ mọi kiểu dữ liệu khác như String, Boolean, Number, Object, hoặc thậm chí là Array.
Ví dụ
const mixedTypedArray = [100, true, 'freeCodeCamp', {}];
Vị trí của phần tử trong mảng gọi là index. Trong Javascript, chỉ số index bắt đầu từ 0 và tăng dần.
Trong ví dụ trên, phần tử 100 có index là 0, true có index là 1.
Ngoài ra độ dài của mảng là số lượng phần tử trong mảng đó, ví dụ trên là 4.
Một chú ý khác, giống trong PHP, mảng của js không cố định chiều dài (định trước số phần tử) giống trong C, C++.
Chúng ta có thể khởi tạp mảng/array trong javascript bởi nhiều cách:
Cách 1
const salad = ['?', '?', '?', '?', '?', '?', '?'];
Cách 2
const salad = new Array('?', '?', '?', '?', '?', '?', '?');
Chú ý: nếu sử dụng new Array(2), bạn sẽ nhận được 1 array với độ dài là 2 với các phần tử trong nó là undefined, nhưng nếu sử dụng new Array(1,2) bạn sẽ nhận được array độ dài 2 với 2 phần tử là 1 và 2..
Ngoài ra còn 1 số cách có thể tạo array như là Array.of, Array.from, hay toán tử (…).
Chúng ta sử dụng dựa trên chỉ số index của phần tử
const element = array[index];
const salad = ['?', '?', '?', '?', '?', '?', '?']; salad[0]; // '?' salad[2]; // '?' salad[5]; // '?'
const salad = ['?', '?', '?', '?', '?', '?', '?']; const len = salad.length; salad[len - 1]; // '?' salad[len - 3]; // '?'
Ngoài ra có thể sử dụng vòng for hoặc hàm forEach
const salad = ['?', '?', '?', '?', '?', '?', '?']; for(let i=0; i<salad.length; i++) { console.log(`Element at index ${i} is ${salad[i]}`); }
Kết quả là
Element at index 0 is ? Element at index 1 is ? Element at index 2 is ? Element at index 3 is ? Element at index 4 is ? Element at index 5 is ? Element at index 6 is ?
Để thêm phần tử vào mảng, ta sử dụng hàm push.
const salad = ['?', '?', '?', '?', '?', '?', '?']; salad.push('?');
Kết quả là
["?", "?", "?", "?", "?", "?", "?", "?"]
Hàm push sẽ thêm phần tử vào cuối của mảng. Trong trường hợp nếu muốn thêm phần tử vào đầu mảng trong javascript chúng ta sử dụng hàm unshift
const salad = ['?', '?', '?', '?', '?', '?', '?']; salad.unshift('?'); Kết quả là ["?", "?", "?", "?", "?", "?", "?", "?"]
Cách đơn giản nhất là dùng hàm pop. Hàm pop sẽ loại bỏ phần tử cuối của mảng, đồng thời trả về phần tử đó.
const salad = ['?', '?', '?', '?', '?', '?', '?']; salad.pop(); // ? console.log(salad); // ['?', '?', '?', '?', '?', '?']
Hàm shift sẽ loại bỏ phần tử đầu mảng và trả về phần tử đó.
const salad = ['?', '?', '?', '?', '?', '?', '?']; salad.shift(); // ? console.log(salad); // ['?', '?', '?', '?', '?', '?'];
Chúng ta có thể dùng hàm slice. Hàm này sẽ tạo ra 1 mảng mới và copy từ mảng gốc.
const salad = ['?', '?', '?', '?', '?', '?', '?']; const saladCopy = salad.slice(); console.log(saladCopy); // ['?', '?', '?', '?', '?', '?', '?'] salad === saladCopy; // returns false
Chúng ta có thể sử dụng toán tử … để thực hiện việc này. Nó sẽ đề cập trong phần tiếp theo của bài viết.
Chúng ta sử dụng hàm isArray
Array.isArray(['?', '?', '?', '?', '?', '?', '?']); // returns true Array.isArray('?'); // returns false Array.isArray({ 'tomato': '?'}); // returns false Array.isArray([]); // returns true
Với ES6 chúng ta có cấu trúc mới để extract thuộc tính (phần tử) của mảng thành các biến lưu giá trị. Việc làm này gọi là destructuring.
let [tomato, mushroom, carrot] = ['?', '?', '?'];
console.log(tomato, mushroom, carrot); // Output, ? ? ?
việc làm này tương đương với việc chúng ta lấy từng phần tử
let vegetables = ['?', '?', '?']; let tomato = vegetables[0]; let mushroom= vegetables[1]; let carrot= vegetables[2];
Khi sử dụng destructuring, khi không có giá trị tương ứng thì biến đó sẽ nhận undefined. Chúng ta có thể gán như sau.
let [tomato , mushroom = '?'] = ['?']; console.log(tomato); // '?' console.log(mushroom ); // '?'
Khi destructuring, bạn có thể bỏ qua phần tử mảng khi extract. Bài toán này hữu dụng khi bạn chỉ muốn chỉ lấy 1 số giá trị trong mảng.
t [tomato, , carrot] = ['?', '?', '?']; console.log(tomato); // '?' console.log(carrot); // '?'
Nested Array Destructuring trong js
Xem ví dụ dưới đây
let fruits = ['?', '?', '?', '?', ['?', '?', '?']];
Nếu ta muốn lấy giá trị ? ra khỏi Array thì cần phải làm thế nào?
Cách 1:
const veg = fruits[4]; // returns the array ['?', '?', '?'] const carrot = veg[2]; // returns '?'
Cách 2
fruits[4][2]; // returns '?
Hoặc cũng có thể dùng như dưới đây
let [,,,,[,,carrot]] = ['?', '?', '?', '?', ['?', '?', '?']];
Từ ES6, chúng ta có thể sử dụng toán tử … (3 dấu chấm) cho Spread và Rest parameter trong destructuring array.
Với Rest Parameter chúng ta có thể map các phần tử bên trái 1 mảng vào 1 mảng mới. Chú ý rằng cú pháp này chỉ áp dụng cho giá trị cuối cùng trong cú pháp destructuring.
const [tomato, mushroom, ...rest] = ['?', '?', '?', '?', '?', '?', '?']; console.log(tomato); // '?' console.log(mushroom); // '?' console.log(rest); // ["?", "?", "?", "?", "?"]
Như ví dụ trên ta thấy rằng, các item ‘?’, ‘?’, ‘?’, ‘?’, ‘?’ sẽ được cho vào 1 array mới.
const salad = ['?', '?', '?', '?', '?', '?', '?']; const saladCloned = [...salad]; console.log(saladCloned); // ["?", "?", "?", "?", "?", "?", "?"] salad === saladCloned // false
Khi sử dụng toán tư này, một mảng mới sẽ được copy từ mảng gốc ban đầu.
Chúng ta có thể hoán đổi giá trị 2 biến bằng cách sử dụng cú pháp destructuring
let first = '?'; let second = '?'; [first, second] = [second, first]; console.log(first); // '?' console.log(second); // '?'
Ví dụ ta có 2 mảng như dưới đây
const emotion = ['?', '?']; const veggies = ['?', '?', '?', '?'];
Chúng ta có thể merge 2 mảng trên bằng cách như sau
const emotionalVeggies = [...emotion, ...veggies]; console.log(emotionalVeggies); // ["?", "?", "?", "?", "?", "?"]
Như phần bên trên đã đề cập, chúng ta đã biết tới các hàm như:
Hàm concat dùng để merge 1 hay nhiều mảng và tgrar về một mảng đã được gộp lại. Mảng được trả về là mảng mới và không thay đổi giá trị mảng gốc ban đầu.
const first = [1, 2, 3]; const second = [4, 5, 6]; const merged = first.concat(second); console.log(merged); // [1, 2, 3, 4, 5, 6] console.log(first); // [1, 2, 3] console.log(second); // [4, 5, 6]
hàm concat cũng có thể để merge nhiều mảng lại với nhau
const first = [1, 2, 3]; const second = [4, 5, 6]; const third = [7, 8, 9]; const merged = first.concat(second, third); console.log(merged); // [1, 2, 3, 4, 5, 6, 7, 8, 9]
Hàm join cho phép nối các phần tử trong mảng lại thành chuỗi. Mặc định ký tự được dùng để nối các phần tử là dấu phẩy “,”.
const emotions = ['?', '?', '?', '?']; const joined = emotions.join(); console.log(joined); // "?,?,?,?"
hoặc bạn có thể thay đổi ký tự nối này
const joined = emotions.join('<=>'); console.log(joined); // "?<=>?<=>?<=>?"
Nếu sử dụng hàm join cho một mảng rỗng, kết quả nhận được là chuỗi rỗng
[].join() // returns ""
Hàm fill array
Hàm fill sẽ lấp đầy (thay thế) một mảng với giá trị mặc định. Chúng ta cũng có thể xác định các phần tử sẽ bị thay thế.
const colors = ['red', 'blue', 'green']; colors.fill('pink'); console.log(colors); // ["pink", "pink", "pink"]
Hoặc nếu chỉ muốn thay thế 2 phần tử cuối cùng
const colors = ['red', 'blue', 'green']; colors.fill('pink', 1,3); // ["red", "pink", "pink"]
Trong đó, tham số đầu tiên của hàm là giá trị muốn thay thế, tham số thứ 2 là vị trí bắt đầu thay thế – bắt đầu từ 0. Tham số cuối cùng là chỉ khi nào sẽ dừng việc thay thế lại. Giá trị này tối đa là bằng colors.length.
Để xác định 1 phần tử có thuộc một mảng cho trước hay không ta sử dụng hàm includes. Nếu phần tử đó được tìm thấy, hàm đó sẽ trả về true, và false trong trường hợp ngược lại.
const names = ['tom', 'alex', 'bob', 'john']; names.includes('tom'); // returns true names.includes('july'); // returns false
Nếu bạn muốn biết vị trí của 1 phần tử trong mảng, hãy sử dụng indexof. Nó sẽ trả về ví trí của phần tử trong mảng, nếu không tìm thấy, giá trị trả về là -1.
const names = ['tom', 'alex', 'bob', 'john']; names.indexOf('alex'); // returns 1 names.indexOf('rob'); // returns -1
Một hàm khác là lastIndexOf() giúp bạn tìm được vị trí cuối cùng của phần tử trong mảng. Trong khi đó hàm indexOf chỉ trả về vị trí đầu tiên của phần. Nói cách khác hàm indexOf sẽ trả về vị trí dầu tiên nếu tại vị trí đó có giá trị bằng giá trị cần tìm.
const names = ['tom', 'alex', 'bob', 'tom']; names.indexOf('tom'); // returns 0 names.lastIndexOf('tom'); // returns 3
Hàm này dùng để đảo ngược mảng, phần tử đầu sẽ thành phần tử cuối và ngược lại.
const names = ['tom', 'alex', 'bob']; names.reverse(); // returns ["bob", "alex", "tom"]
Chú ý rằng, hàm này sẽ sửa trực tiếp mảng gốc ban đầu.
Hàm sort là hàm dùng phổ biến trong việc xử lý mảng trong js. Mặc định, hàm sort sẽ chuyển các phần tử sang dạng string và sau đó sắp xếp chúng. Chiều mặc định sắp xếp là chiều tăng dần. Hàm sort cũng là hàm sẽ thay đổi mảng gốc ban đầu.
const names = ['tom', 'alex', 'bob']; names.sort(); // returns ["alex", "bob", "tom"]
Ví dụ với 1 mảng là các số
const numbers = [23, 5, 100, 56, 9, 13, 37, 10, 1] Khi sử dụng numbers.sort(); kết quả là [1, 10, 100, 13, 23, 37, 5, 56, 9]
Như ví dụ trên, thì đây không phải kết quả chúng ta mong muốn. Bởi lẽ hàm sort đã chuyển các số sang dạng String và so sánh chúng trong hệ mã UTF-16.
Để khắc phục trong trường hợp này ta truyền thêm 1 hàm callback vào trong hàm sort.
function ascendingComp(a, b){ return (a-b); }
Đưa hàm này vào trong hàm sort
numbers.sort(ascendingComp); // retruns [1, 5, 9, 10, 13, 23, 37, 56, 100] /* We could also code it like, numbers.sort(function(a, b) { return (a-b); }); Or, with the arrow function, numbers.sort((a, b) => (a-b)); */
Nếu muốn sắp xếp theo chiều giảm dần thì
numbers.sort((a, b) => (b-a));
Hàm splice giúp bạn thêm, cập nhật hay xóa phần tử trong 1 mảng. Phương thức hơi khó hiểu hơn so với các phương thức khác.
Mục đích chính của hàm splice là xóa các phần tử khỏi mảng. Nó sẽ trả về mảng của các phần tử đã xóa và cập nhật trên mảng gốc. Tuy vậy bạn có thể dùng hàm này cho việc thêm hoặc thay thế các phần tử.
Để thêm phần tử sử dụng hàm splice, chúng ta cần đưa vào vị trí chúng ta muốn thêm, số lượng phần từ muốn xóa bắt đầu từ vị trí nào và các phần tử muốn thêm vào.
Ví dụ dưới đây sẽ thêm phần tử “zack” tại index = 1 mà không xóa bất kì phần tử nào
const names = ['tom', 'alex', 'bob']; names.splice(1, 0, 'zack'); console.log(names); // ["tom", "zack", "alex", "bob"]
Ví dụ dưới đây sẽ xóa 1 phần tử từ index =2 (phần tử thứ 3), sau đso thêm 1 phần tử “zack”. Hàm splice trả về array với phần tử bị xóa “bob”
const names = ['tom', 'alex', 'bob']; const deleted = names.splice(2, 1, 'zack'); console.log(deleted); // ["bob"] console.log(names); // ["tom", "alex", "zack"]
Hãy xem đoạn html dưới đây
<div id="main"> <ul> <ol type="1"> <li>...</li> <li>...</li> <li>...</li> <li>...</li> <li>...</li> <li>...</li> <li>...</li> <li>...</li> <li>...</li> <li>...</li> </ol> </ul> </div>
Chúng ta sử dụng hàm getElementsByTagName để lấy ra toàn bộ li
document.getElementsByTagName('li');
Kết quả thu được là
HTMLCollection không phải là 1 array
Kết quả thu về trông rất giống một array phải không, hãy sử dụng hàm forEach nhé
document.getElementsByTagName('li').forEach(() => { // Do something here.. })
Khi chạy chúng ta sẽ nhận được lỗi bởi vì HTMLCollection không phải là 1 array, đó à một object Array-Like, do đó bạn không thể sử dụng forEach.
Array-like object
Lúc này chúng ta sử dụng hàm Array.from(), nó sẽ chuyển từ 1 object array-like về 1 array
const collection = Array.from(document.getElementsByTagName('li'))
Hàm Array.of()
Hàm Array.of sẽ tạo 1 mảng mới từ dữ liệu đầu vào, dữ liệu này có thể là bất kì kiểu dữ liệu nào và cũng không giới hạn số phần tử
Array.of(2, false, 'test', {'name': 'Alex'})
Kết quả là
Những hàm iterator được sử dụng rất nhiều để duyệt mảng, thực hiện tính toán, lọc…
Cho một mảng students như sau:
let students = [ { 'id': 001, 'f_name': 'Alex', 'l_name': 'B', 'gender': 'M', 'married': false, 'age': 22, 'paid': 250, 'courses': ['JavaScript', 'React'] }, { 'id': 002, 'f_name': 'Ibrahim', 'l_name': 'M', 'gender': 'M', 'married': true, 'age': 32, 'paid': 150, 'courses': ['JavaScript', 'PWA'] }, { 'id': 003, 'f_name': 'Rubi', 'l_name': 'S', 'gender': 'F', 'married': false, 'age': 27, 'paid': 350, 'courses': ['Blogging', 'React', 'UX'] }, { 'id': 004, 'f_name': 'Zack', 'l_name': 'F', 'gender': 'M', 'married': true, 'age': 36, 'paid': 250, 'courses': ['Git', 'React', 'Branding'] } ];
hàm filter sẽ tạo ra một array mới với các phần tử thỏa mãn điều kiện trong hàm callback. Ví dụ hãy tìm tất cả các sinh viên có giới tính là F
const femaleStudents = students.filter((element, index) => { return element.gender === 'F'; }) console.log(femaleStudents);
hàm map sẽ tạo ra một array mới duyệt qua các phần tử và áp dụng 1 biểu thức logic – biểu thức này được cung cấp qua 1 hàm callback.
Ví dụ tạo một mảng chứa full name của tất cả sinh viên
const fullNames = students.map((element, index) => { return {'fullName': element['f_name'] + ' ' + element['l_name']} }); console.log(fullNames);
Kết quả là
Hàm reduce áp dụng 1 hàm reducer cho mỗi phần tử của mảng và trả về giá trị cuối cùng sau khi tính toán.
Ví dụ tính tổng tiền phải trả bởi của tất cả sinh viên
const total = students.reduce( (accumulator, student, currentIndex, array) => { accumulator = accumulator + student.paid; return (accumulator); }, 0); console.log(total); // 1000
Trong đoạn code trên
Hàm này trả về giá trị boolean (true/false) dựa trên dựa trên có ít nhất 1 phần tử của mảng thỏa mãn điều kiện của hàm.
Ví dụ kiểm tra xem có bất kì sinh viên nào ít hơn 30 tuổi không
let hasStudentBelow30 = students.some((element, index) => { return element.age < 30; }); console.log(hasStudentBelow30); // true
Sử dụng hàm some, chúng ta thấy rằng có ít nhất student nhỏ hơn 30 tuổi, vậy làm thế nào để tìm thấy student đó.
Khi đó chúng ta dùng hàm find, hàm find sẽ trả về phần tử đầu tiên thỏa mãn điều kiện.
Ngoài ra còn có hàm findIndex giống như find nhưng nó trả về index của phần tử tìm thấy. Nếu không có phần tử nào tìm thấy, hàm findIndex trả về -1.
const student = students.find((element, index) => { return element.age < 30; }); console.log(student);
Kết quả là
Hàm every kiểm tra xem mọi phần tử trong array có thỏa mãn điều kiện hay không
Ví dụ kiểm xem tất cả các student có đăng ký ít nhất 2 khóa học hay không?
const atLeastTwoCourses = students.every((elements, index) => { return elements.courses.length >= 2; }); console.log(atLeastTwoCourses); // true
Hàm at() giúp chúng ta truy cập phần tử thông qua chỉ số index, tuy vậy chỉ số index này có thể là số âm.
const junkFoodILove = ['?', '?', '?', '?', '?', '?', '?', '?']; junkFoodILove.at(0); // ? junkFoodILove.at(3); // ? junkFoodILove.at(-1); // ? junkFoodILove.at(-5); // ? junkFoodILove.at(-8); // ? junkFoodILove.at(10); // undefined
Bài viết được dịch từ https://www.freecodecamp.org/news/the-javascript-array-handbook/
Hi vọng sau bài viết này các bạn đã hiểu rõ hơn về array trong javascript. Từ đó có thể vận dụng tối đa cách sử dụng để đạt hiệu quả lớn nhất cho công việc của mình.
Bình luận: