[Javascript] Những phương thức mà bạn cần biết khi thao tác với mảng

Giới thiệu

Xin chào mọi người, buổi trước mình có viết bài về xử lý mảng trong ruby nhưng vấn đề là không phải lúc nào mình cũng làm việc đó ở bên back-end đúng không.
Thế nên hôm này mình sẽ bổ xung thêm cách xử lý mảng trong javascript cho nó có đôi có cặp, nói thế thôi chứ thực ra thì chúng giống na ná nhau đến 80% rồi nên cũng không có gì mới mẻ lắm đâu.
Lets' go. Hãy tạo 1 mảng trước đã:

var foods = ['apple', 'tangerine', 'poultry_leg', 'pizza', 'hotdog']

1. Length

Sẽ trả về tổng số phần tử của mảng.

f.length;  // 5

Hầu hết mọi người thường làm rỗng một mảng bằng cách gán nó bằng một mảng rỗng, nhưng như thế có thật sự hiệu quả không?

let foo = [1, 2, 3];
let bar = [1, 2, 3];
let foo2 = foo;
let bar2 = bar;
foo.length = 0;          // so good
bar = [];                // not good
console.log(foo, foo2);  // [] []
console.log(bar, bar2);  // [] [1, 2, 3]

Khi làm rỗng một mảng bằng cách gán nó bằngrỗng thì hiểu đơn giản là mảng đó sẽ quên đi địa chỉ ô nhớ lưu giá trị [1, 2, 3] và sẽ nhận địa chỉ ô nhớ lưu giá trị [] => dữ liệu cũ không bị xóa đi mà còn tạo thêm một mảng mới với giá trị rỗng.
Gán độ dài của mảng đó về không thì lại khác, việc này sẽ trực tiếp thao tác với địa chỉ ô nhớ lưu giá trị [1, 2, 3] và gán cho địa chỉ ô nhớ đó về rỗng.
Tip: Cách đơn giản cũng như hiệu quả nhất là sử dụng .length = 0 để làm rỗng một mảng

foods.length = 2;  // ['apple', 'tangerine']
foods.length = 0;  // []

2. Push

Thêm một phẩn tử vào vị trí cuối cùng của mảng.

foods.push('grape');
foods;  // ['apple', 'tangerine', 'poultry_leg', 'pizza', 'hotdog', 'grapes']

Tip: Thêm nhiều phần tử trong mảng thông qua Spread syntax (...) - một tính năng tương đối hay của ES6 có thể thay thế cho hàm concat.

let numbers =  [1, 2, 3, 4, 5, 6];
let num2 = [7, 8, 9];
numbers.push(...num2);  // [1, 2, 3, 4, 5, 6, 7, 8, 9]

3. Unshift

Thêm một phần tử vào đầu của mảng.

foods.unshift('grape');
foods;  // [ 'grapes', 'apple', 'tangerine', 'poultry_leg', 'pizza', 'hotdog']

Tip: Thêm nhiều phần tử trong mảng thông qua Spread syntax (...)

let numbers =  [1, 2, 3, 4, 5, 6];
let num2 = [7, 8, 9];
numbers.unshift(...num2); // [7, 8, 9, 1, 2, 3, 4, 5, 6]

4. Pop

Xóa bỏ một phần tử cuối cùng của mảng và trả về phần tử vừa được xóa.

foods;           // ['apple', 'tangerine', 'poultry_leg', 'pizza', 'hotdog']
foods.pop();     // "hotdog"
foods;           // ['apple', 'tangerine', 'poultry_leg', 'pizza']

5. Shift

Xóa bỏ một phần tử đầu tiên của mảng và cũng trả về phẩn tử vừa được xóa.

foods;           // ['apple', 'tangerine', 'poultry_leg', 'pizza', 'hotdog']
foods.shift();   // "apple"
foods;           // ['tangerine', 'poultry_leg', 'pizza',  'hotdog']

6. Join

Nối các phần tử của một mảng lại với nhau thành một chuỗi.

foods;            // ['apple', 'tangerine', 'poultry_leg', 'pizza', 'hotdog']
foods.join();     // "apple,tangerine,poultry_leg,pizza,hotdog"
foods.join('');   // "appletangerinepoultry_legpizzahotdog" 
foods.join('-');  // "apple-tangerine-poultry_leg-pizza-hotdog"

7. Concat

Kết hợp các mảng lại với nhau:

let array = [0, 1];
let newArray = array.concat(2, [3, 4, [5, 6], 7], 8, 9, undefined, null);
// [0, 1, 2, 3, 4, [5, 6], 7, 8, 9, undefined, null]

Tip: Cũng có thể sử dụng Spread syntax - (...) thay có concat

let languages = ["JavaScript", "Ruby", "SQL"]
let frameworks = ["React", "Rails"]
let myStack = languages.concat(frameworks)
let myStack = [...languages, ...frameworks]
// ["JavaScript", "Ruby", "SQL", "React", "Rails"]

8. Reverse

Đảo ngược vị trí của các phẩn tử trong một mảng.

foods;           // ['apple', 'tangerine', 'poultry_leg', 'pizza', 'hotdog']
foods.reverse();
foods;           // ['hotdog', 'pizza', 'poultry_leg', 'tangerine', 'apple']

Tip: Đảo ngược một chuỗi (convert sang mảng -> đảo ngược -> convert lại string)

let str = "Athena"
let strReverse = [...str].reverse().join(''); // "anehtA"

9. indexOf và lastIndexOf

indexOf trả về chỉ mục của phẩn tử tìm thấy đầu tiên trong mảng đó, nếu không có sẽ trả về -1.
lastIndexOf trả về chỉ mục của phần tử tìm thấy cuối cùng trong mảng đó, nếu không có sẽ trả về -1.

foods;  // ['apple', 'tangerine', 'beef', 'pizza', 'apple', 'hotdog']
apple tangerine beef pizza apple hotdog egg
Index 0 1 2 3 4 5 -
indexOf 0 1 2 3 0 5 -1
lastIndexOf 4 1 2 3 4 5 -1
foods.indexOf('apple');      // 0
foods.lastIndexOf('apple');  // 4
foods.indexOf('egg');        //-1

10. Some

Kiểm tra nếu như có bất kỳ một phần tử nào thỏa mãn điều kiện đề ra thì trả vềtrue.

let num = [1, 2, 3, 4, 5];
num.some(item => item > 3);  // true
num.some(item => item > 6);  // false

Trên là cách viết rút gọn sử dụng arrow function trong ES6 còn cú pháp đầy đủ sẽ như sau:

num.some(function(item){return item > 3});

11. Every

Nghiêm ngặt hơn đó là every, chỉ trả về true khi tất cả các phần tử thỏa mãn điều kiện đề ra.

let num = [1, 2, 3, 4, 5];
num.some(item => item > 3);  // false
num.some(item => item > 0);  // true

12. Sort

Sắp xếp các phần tử trong mảng, nếu không truyền vào điều kiện gì thì mặc định sẽ sắp xếp theo char code.

let arr = ['b', 'c', 'd', 'e'];
arr.sort();  // ["b", "c", "d", "e"]

//custom sort
let num = [1, 2, 3, 4, 5, 100, 23, 12];
num.sort( (a, b) => a-b );  // [1, 2, 3, 4, 5, 12, 23, 100]

Note: Hãy cẩn thận khi sử dụng sort, nên nhớ rằng phương thức này sắp xếp dựa trên char code chứ không phải giá trị, ví dụ điển hình là 100 > 2 nhưng lại "100" < "2".

let num = [1, 2, 3, 4, 5, 100, 23, 12];
num.sort();  // [1, 100, 12, 2, 23, 3, 4, 5]

Tip: Xáo trộn một mảng bằng sort.

let arr = [1,2,4,1,2,3];
arr.sort(() => Math.random()-0.5);

13. Filter

Phương thức filter() tạo ra một mảng mới dự trên các điều kiện mà trả về kết quả true từ một mảng hiện có.

foods;     // ['apple', 'tangerine', 'poultry_leg', 'pizza', 'hotdog']
let vegFoods =  foods.filter( food => isVeg(food));
vegFoods;  // ['apple', 'tangerine', 'pizza']

14. Reduce

Phương thức reduce() thực thi các phương thức xử lý đối với từng phần tử trong mảng và cuối cùng tổng hợp kết quả về trả về cho chúng ta.
Hãy xem một ví dụ đơn giản:

let numbers = [1, 2, 3, 4, 5];
let result = 0;
//  cách 1
function add(res, currentNum){ return res+ currentNum};
numbers.reduce(add, result);                                   // 15

//  cách 2: dùng arrow function
numbers.reduce((res, currenNum) => res + currenNum, result);   // 15

15. ReduceRight

Tương tự như reduce nhưng các phần tử truyền vào theo thứ tự từ phải qua trái (phần tử cuối cùng chạy trước, phần tử đầu tiên chạy sau cùng).

let array = [1,2,3,4,5];
let result = 0;
function sum(result, num) {
   console.log(num);
   return result + num;
}
array.reduce(sum, result);
// từ trái qua phải i.e., 1,2,3,4,5

array.reduceRight(sum, result);
// từ phải qua trái i.r., 5,4,3,2,1

array.reduceRight( (res, num) => res+num, result);
// with arrow function

16. Map

Bạn muốn biến đổi dữ liệu của từng phần tử trong một mảng, hoặc bạn muốn lấy ra những thuộc tính của đối tượng trong mảng thì lúc đó hãy sử dụng map.
Map cho phép bạn tùy biến dữ liệu trên từng phần tử (cộng trừ nhân chia, thêm bớt các kiểu) để rồi ta được một mảng mới đã có dữ liệu từ mảng ban đầu nhưng đã qua xử lý.

let numbers = [1, 2, 3, 4, 5];
// cách 1: Viết đầy đủ
function double(num){return num*num};
numbers.map(double);  // [1, 4, 9, 16, 25]

// cách 2: Dùng arrow function
numbers.map(num => num*num);

17. Splice

Phương thức splice(ịndex, n, m) sẽ xóa bỏ n phần tử tính từ index trở đi và cũng thêm vào những phần tử mong muốn - m.

let array = [1, 2, 4, 5];
array.splice(2, 0, 3);             // tại vị trí index = 2: xóa đi 0 phần tử  rồi sau đó chèn vào 3
array;  // [1, 2, 3, 4, 5]

array.splice(2, 1, 30, 95);       // tại vị trí index = 2: xóa đi 1 phần tử  rồi sau đó chèn vào 30, 95
array;  // [1, 2, 30, 95, 4, 5]

array.splice(2, 0);               // tại vị trí index = 2: xóa đi 0 phần tử  phía sau đó
array;   // [1, 2, 30, 95, 4, 5]

array.split(2);                  // tại vị trí index = 2: xóa đi tất cả các phần tử  phía sau đó
array;   // [1, 2]

18. Slice

Phương thức slice(start, end) trả về một bản sao từ mảng ban đầu, trong đó:
start: vị trí bắt đầu trính xuất
end: vị trí kêt thúc, kết quả sẽ không bao gồm phần tử end.

let numbers = [1, 2, 3, 4, 5];
numbers.slice(1);     // [2, 3, 4, 5]
numbers.slice(1, 3);  // [2, 3]

Tip: Lấy ra n phần tử cuối cùng một mảng

// get last n elements
array.slice(-n);

let numbers = [1, 2, 3, 4, 5];
numbers.slice(-1);  // 5
numbers.slice(-3);  // [3, 4, 5]

19. forEach

Thực thi một callback function với từng phần tử trong mảng. Chúng ta không thể sử dung breakcontinue trong forEach:

let numbers = [1, 2, 3, 4, 5];
numbers.forEach( e => console.log(e));

Bonus

1. Loại bỏ phần tử trùng lặp

const array = [1, 1, 2, 3, 5, 5, 1]
const uniqueArray = [...new Set(array)];
uniqueArray); // Result: [1, 2, 3, 5]

2. Lấy ra những phần tử cuối cùng trong một mảng

Đó là một mẹo trong khi sử dụng slice mình có nêu ở bên trên.

let array = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
array.slice(-1); // Result: [9]
array.slice(-2); // Result: [8, 9]
array.slice(-3); // Result: [7, 8, 9]

3. Duỗi thẳng một mảng

Trong ES2019 có đưa thêm một hàm đó là flat()
Hàm này nhận duỗi thẳng một mảng tùy theo số ta truyền vào.

let array = [0, 1, 2, [3, [[4, 5], [6], 7], 8, 9], 10 , [11]];
array.flat(1);  // [0, 1, 2, 3, [[4, 5], [6], 7], 8, 9, 10, 11]
array.flat(2);  // [0, 1, 2, 3, [4, 5], [6], 7, 8, 9, 10, 11]
array.flat(3);  // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]

Tham khảo

https://medium.com/better-programming/20-methods-to-get-to-know-javascript-array-operations-6935e757729b
https://medium.com/@PurpleGreenLemon/simplify-your-javascript-with-these-6-array-methods-db4c278f08c9


All Rights Reserved