9 Ways to Remove Elements From A JavaScript Array - Plus How to Safely Clear JavaScript Arrays

  Javascript    —  2019, Jul 25    

Javascript là một ngôn ngữ hay. Mảng trong Javascript cũng kì diệu. Đôi lần làm việc với mảng mà choáng váng đầu khi không thể tìm thấy một method kiểu như Array.remove hay Array.delete gì cả.

Cũng chẳng sao, vì nếu không có các method sẵn có thì mình có thể tự viết method thôi.

Xóa phần tử ở cuối thì đã có pop(), xóa phần tử đầu thì đã có shift() hoặc xóa phần tử ở giữa thì đã có splice. Còn muốn mảng mới với các phần tử được lọc thì nâng cao hơn là filter().

  • pop - xóa phần tử cuối mảng
  • shift - xóa phần tử đầu mảng
  • splice - xóa phần tử ở vị trí xác định của mảng
  • filter - tùy chỉnh xóa các phẩn tử trong mảng

Nào, cùng lướt qua vài cách để xóa phần tử khỏi mảng nhé:

Xóa phần tử cuối mảng

Có thể sử dụng thuộc tính length của mảng để xóa các phần tử cuối mảng. Các phần tử có index lớn hơn hoặc bằng với giá trị new length thì sẽ bị xóa bỏ.

var ar = [1, 2, 3, 4, 5, 6];
ar.length = 4; // set length to remove elements
console.log( ar ); //  [1, 2, 3, 4]

Hàm pop() sẽ xóa phần tử cuối của mảng, trả lại giá trị phần tử đó và cập nhật lại độ dài của mảng.

var ar = [1, 2, 3, 4, 5, 6];
ar.pop(); // returns 6
console.log( ar ); // [1, 2, 3, 4, 5]

Xóa phần tử đầu mảng

Hàm shift() khá giống với hàm pop. Chỉ khác là nó xóa phần tử đầu mảng mà thôi.

var ar = ['zero', 'one', 'two', 'three'];
ar.shift(); // returns "zero"
console.log( ar ); // ["one", "two", "three"]

Hàm shift sẽ trả về giá trị của phần tử đã xóa, cập nhật lại index của các phần tử còn lại trong mảng, và cập nhật lại độ dài mảng.

Nếu mà không có phần tử nào hoặc mảng có độ dài là 0 thì trả về undefined.

Sử dụng Splice để xóa phần tử trong mảng

Hàm splice có thể thêm hoặc xóa phần tử trong một mảng. Với tham số thứ nhất là vị trí bắt đầu thêm hoặc xóa, tham số thứ 2 là số lượng phần tử xóa. Tham số thứ 3 tùy chọn; có thể chỉ ra phaafnf tử được thêm vào.

Trong mảng thì vị trí đầu tiên là 0.

var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0];
var removed = arr.splice(2,2);

/*
removed === [3, 4]
arr === [1, 2, 5, 6, 7, 8, 9, 0]
*/

Hàm splice cũng dùng để xóa 1 dải các phần tử từ mảng.

["bar", "baz", "foo", "qux"]

list.splice(0, 2) 
// Starting at index position 0, remove two elements ["bar", "baz"] and retains ["foo", "qux"].

Xóa phần tử trong mảng bằng giá trị sử dụng splice

var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0];

for( var i = 0; i < arr.length; i++){ 
   if ( arr[i] === 5) {
     arr.splice(i, 1); 
   }
}

//=> [1, 2, 3, 4, 6, 7, 8, 9, 0]

Đây là 1 ví dụ đơn giản với các phần tử là kiểu integer. Trường hợp các phần tử là các objects thì sẽ phức tạp hơn 1 chút.

Đoạn code trên chỉ remove đi 1 phần tử, nếu muốn xóa nhiều phần tử thì có vẻ không ổn với đoạn code trên.

Vì phần tử được xóa khỏi mảng mà giá trị index vẫn tăng và ở phần tử kế tiếp sau giá trị được match sẽ bị bỏ qua.

Để giải quyết vấn đề này thì có thể sử dụng đoạn code bên dưới. Việc giảm đi giá trị index thì nó sẽ không bỏ qua phần tử tiếp theo trong mảng.

var arr = [1, 2, 3, 4, 5, 5, 6, 7, 8, 5, 9, 0];

for( var i = 0; i < arr.length; i++){ 
   if ( arr[i] === 5) {
     arr.splice(i, 1); 
     i--; // thêm đoạn này để không bị bỏ qua phần tử kế tiếp khi mà i++
   }
}

//=> [1, 2, 3, 4, 6, 7, 8, 9, 0]

Sử dụng hàm filter để xóa phần tử bằng giá trị

Không giống như phương thức splice, filter tạo ra 1 mảng mới. Hàm filter() không thay đổi mảng khi được gọi mà trả về 1 mảng mới.

filter() có 1 tham số và một callback. Callback được gọi như là 1 hàm filter và lặp qua từng phần tử. Hàm callback có 3 phần tử: giá trị hoặc phần tử hiện tại, index của phần tử hiện tại, mảng hiện tại.

Callback sẽ trả về true hoặc false, nếu là true thì phần tử hiện tại sẽ được thêm vào mảng mới (filtered array)

var array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0];

var filtered = array.filter(function(value, index, arr){

    return value > 5;

});

//filtered => [6, 7, 8, 9]
//array => [1, 2, 3, 4, 5, 6, 7, 8, 9, 0]

Khuyên bạn là nên gán các mảng đã được filter vào 1 mảng mới. Vì nó hữu ích trong trường hợp bạn muốn sử dụng lại cả dữ liệu của mảng gốc. Okay boy! :D

Sử dụng thư viện Lodash để xóa phần tử

Nếu bạn ngại phải custom một method cho chức năng xóa phần tử trong mảng thì có thể dùng hàm remove trong thư viện Lodash.

Hàm remove trong Lodash làm việc giống như hàm filter nhưng được sắp xếp ngược lại. Nó không giữ giá trị của mảng ban đầu, xóa các phần tử được match. Nó trả về các phần tử được match như 1 new aray.

var array = [1, 2, 3, 4];
var evens = _.remove(array, function(n) {
  return n % 2 === 0;
});

console.log(array);
// => [1, 3]

console.log(evens);
// => [2, 4]

Tạo một hàm remove

function arrayRemove(arr, value) {

   return arr.filter(function(ele){
       return ele != value;
   });

}

var result = arrayRemove(array, 6);

// result = [1, 2, 3, 4, 5, 7, 8, 9, 0]

Hàm này rất cơ bản, và giả sử là chỉ sử dụng với giá trị kiểu numbers hoặc strings. Nếu giá trị là các kiểu phức tạp hơn thì bạn nên customer lại cho phù hợp.

Sử dụng toán tử delete để xóa hoàn toàn phần tử trong mảng

var ar = [1, 2, 3, 4, 5, 6];
delete ar[4]; // delete element with index 4
console.log( ar ); // [1, 2, 3, 4, undefined, 6]
alert( ar ); // 1,2,3,4,,6

Toán tử delete không ảnh hưởng tới length, cũng không ảnh hưởng tới indexs của các phần tử kế tiếp. Thực tế phần tử bị delete sẽ có giá trị là undefined.

Toán tử delete được thiết kế để xóa các thuộc tính của objects mà array lại là objects

Lý do phần tử không thực sự bị xóa khỏi mảng là do toán tử delete liên quan tới việc giải phóng bộ nhớ hơn là xóa phần tử. Bộ nhớ được giải phóng khi không còn tham chiếu tới giá trị.

Clear hoặc Reset mảng

Đây là cách đơn giản mà ai cũng làm

var ar = [1, 2, 3, 4, 5, 6];

//do stuff

ar = [];

//a new, empty array!

Nhưng sử dụng cách trên sẽ có 1 vấn đề là nếu bạn gán mảng vào 1 biến khác. Thì các tham chiếu đó sẽ không thay đổi mà vẫn giữ các giá trị của mảng ban đầu. Nó có thể tạo ra bug🐛 tiềm ẩn trong chương trình.

Ví dụ đơn giản về điều này:

var arr1 = [1, 2, 3, 4, 5, 6];

var arr2 = arr1;  // Reference arr1 by another variable 

arr1 = [];

console.log(arr2); // Output [1, 2, 3, 4, 5, 6]

Cách khác đơn giản là thiết lập length của mảng về 0

var ar = [1, 2, 3, 4, 5, 6];

console.log(ar); // Output [1, 2, 3, 4, 5, 6]

ar.length = 0;

console.log(ar); // Output []

Cách khác là kết hợp phương thức splice và thuộc tính length của mảng làm tham số thứ 2. Kết quả trả về 1 bản sao khác của mảng ban đầu.

var ar = [1, 2, 3, 4, 5, 6];

console.log(ar); // Output [1, 2, 3, 4, 5, 6]

ar.splice(0, ar.length);

console.log(ar); // Output []

2 cách trên sẽ không tạo ra 1 mảng mới mà thay đổi các phần tử của mảng. Có nghĩa là mọi tham chiếu đều được update.

Còn có thêm cách khác nữa là sử dụng vòng lặp while, hơi lạ phải không, nhưng thú vị đấy và có thể gây ấn tượng cho 1 số bạn bè đấy :D.

var ar = [1, 2, 3, 4, 5, 6];

console.log(ar); // Output [1, 2, 3, 4, 5, 6]

  while (ar.length) {
    ar.pop();
  }

console.log(ar); // Output []

Đây là 1 trong vô vàn các cách làm để xóa phần tử ra khỏi mảng trong Javascript. Tuy nhiên xét về performance thì các cách trên đây là tốt, nhanh và rất dễ đọc.

Túm cái váy lại là mặc dù Javascript không hề có phương thức remove nào cho mảng. Nhưng với các phương thức khác thì chúng ta vẫn có thể tạo ra được 1 phương thức remove tùy ý.

Vì mảng là rất quan trọng trong việc quản lý dữ liệu, nên hãy thực sự làm việc tốt với mảng nhé! :D