12/08/2018, 15:36

Cùng tìm hiểu map, filter và reduce trong javascript

Khi làm việc trên các dự án Javascript, bạn không thể tránh khỏi những tình huống mà bạn phải làm một số thao tác trên data. Bạn luôn có thể sử dụng các vòng lặp for để có được kết quả mong muốn , nhưng for-loops có thể nhanh chóng gây ra một số rắc rối và có thể rắc rối đó sẽ lớn hơn nếu bạn ...

Khi làm việc trên các dự án Javascript, bạn không thể tránh khỏi những tình huống mà bạn phải làm một số thao tác trên data. Bạn luôn có thể sử dụng các vòng lặp for để có được kết quả mong muốn , nhưng for-loops có thể nhanh chóng gây ra một số rắc rối và có thể rắc rối đó sẽ lớn hơn nếu bạn chưa hiểu rõ về nó. Trong hầu hết mọi trường hợp việc sử dụng map, filter hoặc reduce là rất dễ dàng.Code của bạn vẫn sạch hơn và dễ đọc hơn.Nhưng ít nhất bạn hiểu về chúng hoạt động như thế nào và khi nào sử dụng chúng đó sẽ là điều tốt nhất cho bạn.

Có một số rule mà tôi đang sử dụng chia sẻ như sau: 1.Nếu tôi có một mảng và tôi muốn làm chính xác cùng một action trên mỗi yếu tố trong mảng và trả lại cùng 1 số lượng các đối tượng trong mảng thì nên sử dụng map. 2.Nếu tôi đã có mảng nhưng tôi chỉ muốn có các đối tượng trong mảng phù hợp với tiêu chí nhất định thì nên sử dụng filter. 3.Nếu tôi đã có 1 mảng. nhưng tôi muốn sử dụng các giá trị trong mảng đó để tạo ra một cái gì đó mới thì sử dụng reduce. Nói ra những quy tắc này mọi người nghe có vẻ mơ hồ, vậy nên chúng ta sẽ xét 1 số ví dụ để hiểu rõ hơn .Đối với ví dụ của tôi, tôi sử dụng một mảng animal như sau:

  {
      "name": "cat",
      "size": "small",
      "weight": 5
  },
  {
      "name": "dog",
      "size": "small",
      "weight": 10
  },
  {
      "name": "lion",
      "size": "medium",
      "weight": 150
  },
  {
      "name": "elephant",
      "size": "big",
      "weight": 5000
  }
] 

Map operator

Giả sử chúng ta muốn có một mảng với tên của tất cả các loài động vât. Việc sử dụng 1 vòng for-loop chúng ta sẽ viết như sau:

let animal_names = [];

for (let i = 0; i < animals.length; i++) {
    animal_names.push(animals[i].name);
}

Đối với map sẽ được sử dụng như thế này:

let animal_names = animals.map((animal, index, animals) => {
    return animal.name
})

Map sử dụng 3 giá trị trong hàm , cụ thể là: 1.Đối tượng hiện tại của mảng 2.Mảng hiện tại của đối tượng 3.Toàn bộ giá trị của mảng Trong khi đây là một ví dụ rất dễ dàng, tuy nhiên chúng ta có 1 sự thay đổi trong việc đọc mã code:

  • Sử dụng map, chúng ta không cần quản lý đến trạng thái của vòng lặp for-loop
  • Chúng ta không cần phải sử dụng index để chỉ đúng array cho vòng lặp đó
  • Chúng ta không cần tạo một mảng mới và đẩy các giá trị của chúng ta vào nó. Thay vì làm điều đó map đã trả về mảng hoàn chỉnh trong 1 lần.Vì vậy chúng ta chỉ cần gán cho nó thêm 1 biến .Có 1 điều rất quan trọng mà bạn có thể không bao giờ quên khi sử dụng map là phải sử dụng câu lệnh Return nếu không mảng của bạn sẽ kết thúc với tất cả item là undefined.

Filter operator

Hỏi rằng nếu chúng ta chỉ muốn mảng có những động vật nhỏ, For-loop sẽ sử dụng như thế nào:

let small_animals = [];

for (let i = 0; i < animals.length; i ++) {
    if (animals[i].size === "small") {
        small_animals.push(animals[i])
    }
}

Trong khi đó filter sẽ được sử dụng như sau:

let small_animals = animals.filter((animal) => {
    return animal.size === "small"
})

Filter chấp nhận các tham số giống nhau ( current item, index, entie array) trong hàm return. Nhưng vì chúng ta không sử dụng index và entie array nên tôi đã bỏ chúng ra. Filter cũng có những lợi ích tương tự map. Chúng ta cũng phải sử dụng return để làm cho filter hoạt động bình thường. Nhưng chắc chắn 1 điều là giá trị trả về là boolean nếu bạn không làm điều này giá trị default là false.

Reduce operator

Nếu muốn tính trọng lượng của tất cả các con vật trong array chúng ta sử dụng một for-loop như sau:

let total_weight = 0;

for (let i = 0; i < animals.length; i++) {
    total_weigth += animals[i].weight
}

Thay vì đó chúng ta sử dụng như sau với reduce:

let total_weight = animals.reduce((weight, animal, index, animals) => {
    return weight += animal.weight
}, 0)

Các tham số trong hàm callback gọi lại hoạt động khác một chút so với map và filter. Nó hoạt động như sau: 1.Tham số đầu tiên là giá trị hiện tại của giá trị kết thúc. Nghĩa là chúng ta phải đặt giá trị ban đầu vào cuối của hàm. Trong trường hợp này chúng ta đặt nó là 0.Điều này đúng với moị giá trị. 2.Tham số thứ 2 là current item 3.Tham số thứ 3 là index 4.Cuối cùng là mảng đầy đủ. Một lần nữa chúng ta có các cách mới để có thể đọc được map và filter và reduce.Điều quan trọng là chúng ta trả lại giá trị cuối, tham số đầu tiên , vào cuối mỗi hàm reduce.

Kết luận

Sau những ví dụ đơn giản này bạn cần hiểu rõ hơn cách sử dụng filter map và reduce . Những cách sử dụng này sẽ làm rõ ràng dễ hiểu hơn code của bạn nhất là khi thao tác với các dữ liệu có độ phức tạp cao. Tôi khuyên ban nên tìm hiểu về nó sâu hơn kể cả khi bạn không sử dụng đến chúng.

Thank for reading !

0