Khai phá sức mạnh của lập trình hướng chức năng với mảng JavaScript. Học cách biến đổi, lọc và giảm dữ liệu hiệu quả bằng các phương thức tích hợp.
Làm chủ Lập trình Hướng chức năng với Mảng JavaScript
Trong bối cảnh phát triển web không ngừng phát triển, JavaScript tiếp tục là một nền tảng cốt lõi. Trong khi các mô hình lập trình hướng đối tượng và mệnh lệnh từ lâu đã chiếm ưu thế, lập trình hướng chức năng (FP) đang ngày càng thu hút được sự chú ý. FP nhấn mạnh tính bất biến, các hàm thuần túy và mã khai báo, dẫn đến các ứng dụng mạnh mẽ hơn, dễ bảo trì hơn và có thể dự đoán được hơn. Một trong những cách mạnh mẽ nhất để áp dụng lập trình hướng chức năng trong JavaScript là tận dụng các phương thức mảng gốc của nó.
Hướng dẫn toàn diện này sẽ đi sâu vào cách bạn có thể khai thác sức mạnh của các nguyên tắc lập trình hướng chức năng bằng cách sử dụng các mảng JavaScript. Chúng ta sẽ khám phá các khái niệm chính và trình bày cách áp dụng chúng bằng các phương thức như map
, filter
và reduce
, thay đổi cách bạn xử lý thao tác dữ liệu.
Lập trình Hướng chức năng là gì?
Trước khi đi sâu vào mảng JavaScript, hãy cùng định nghĩa ngắn gọn về lập trình hướng chức năng. Về cốt lõi, FP là một mô hình lập trình coi tính toán là việc đánh giá các hàm toán học và tránh thay đổi trạng thái và dữ liệu có thể thay đổi. Các nguyên tắc chính bao gồm:
- Các hàm thuần túy: Một hàm thuần túy luôn tạo ra cùng một kết quả cho cùng một đầu vào và không có tác dụng phụ (nó không sửa đổi trạng thái bên ngoài).
- Tính bất biến: Dữ liệu, một khi đã được tạo, không thể thay đổi. Thay vì sửa đổi dữ liệu hiện có, dữ liệu mới sẽ được tạo với các thay đổi mong muốn.
- Hàm hạng nhất: Các hàm có thể được coi như bất kỳ biến nào khác – chúng có thể được gán cho các biến, truyền dưới dạng đối số cho các hàm khác và trả về từ các hàm.
- Khai báo so với Mệnh lệnh: Lập trình hướng chức năng nghiêng về phong cách khai báo, nơi bạn mô tả những gì bạn muốn đạt được, thay vì phong cách mệnh lệnh chi tiết cách để đạt được điều đó từng bước.
Áp dụng các nguyên tắc này có thể dẫn đến mã dễ suy luận, kiểm thử và gỡ lỗi hơn, đặc biệt là trong các ứng dụng phức tạp. Các phương thức mảng của JavaScript hoàn toàn phù hợp để triển khai các khái niệm này.
Sức mạnh của các Phương thức Mảng JavaScript
Các mảng JavaScript đi kèm với một bộ phương thức tích hợp phong phú cho phép thao tác dữ liệu tinh vi mà không cần dùng đến các vòng lặp truyền thống (như for
hoặc while
). Các phương thức này thường trả về các mảng mới, thúc đẩy tính bất biến và chấp nhận các hàm callback, cho phép cách tiếp cận chức năng.
Hãy cùng khám phá các phương thức mảng chức năng cơ bản nhất:
1. Array.prototype.map()
Phương thức map()
tạo một mảng mới được điền bằng kết quả của việc gọi một hàm được cung cấp cho từng phần tử trong mảng gọi nó. Nó lý tưởng để biến đổi từng phần tử của mảng thành một thứ gì đó mới.
Cú pháp:
array.map(callback(currentValue[, index[, array]])[, thisArg])
callback
: Hàm được thực thi cho mỗi phần tử.currentValue
: Phần tử hiện tại đang được xử lý trong mảng.index
(tùy chọn): Chỉ mục của phần tử hiện tại đang được xử lý.array
(tùy chọn): Mảng màmap
đã được gọi trên đó.thisArg
(tùy chọn): Giá trị được sử dụng làmthis
khi thực thicallback
.
Đặc điểm chính:
- Trả về một mảng mới.
- Mảng gốc không bị thay đổi (tính bất biến).
- Mảng mới sẽ có cùng độ dài với mảng gốc.
- Hàm callback nên trả về giá trị đã biến đổi cho mỗi phần tử.
Ví dụ: Nhân đôi mỗi Số
Hãy tưởng tượng bạn có một mảng các số và bạn muốn tạo một mảng mới nơi mỗi số được nhân đôi.
const numbers = [1, 2, 3, 4, 5];
// Sử dụng map để biến đổi
const doubledNumbers = numbers.map(number => number * 2);
console.log(numbers); // Output: [1, 2, 3, 4, 5] (mảng gốc không thay đổi)
console.log(doubledNumbers); // Output: [2, 4, 6, 8, 10]
Ví dụ: Trích xuất Thuộc tính từ Đối tượng
Một trường hợp sử dụng phổ biến là trích xuất các thuộc tính cụ thể từ một mảng các đối tượng. Giả sử chúng ta có danh sách người dùng và chỉ muốn lấy tên của họ.
const users = [
{ id: 1, name: 'Alice' },
{ id: 2, name: 'Bob' },
{ id: 3, name: 'Charlie' }
];
const userNames = users.map(user => user.name);
console.log(userNames); // Output: ['Alice', 'Bob', 'Charlie']
2. Array.prototype.filter()
Phương thức filter()
tạo một mảng mới với tất cả các phần tử vượt qua bài kiểm tra được thực hiện bởi hàm được cung cấp. Nó được sử dụng để chọn các phần tử dựa trên một điều kiện.
Cú pháp:
array.filter(callback(element[, index[, array]])[, thisArg])
callback
: Hàm được thực thi cho mỗi phần tử. Nó nên trả vềtrue
để giữ lại phần tử hoặcfalse
để loại bỏ nó.element
: Phần tử hiện tại đang được xử lý trong mảng.index
(tùy chọn): Chỉ mục của phần tử hiện tại.array
(tùy chọn): Mảng màfilter
đã được gọi trên đó.thisArg
(tùy chọn): Giá trị được sử dụng làmthis
khi thực thicallback
.
Đặc điểm chính:
- Trả về một mảng mới.
- Mảng gốc không bị thay đổi (tính bất biến).
- Mảng mới có thể có ít phần tử hơn mảng gốc.
- Hàm callback phải trả về một giá trị boolean.
Ví dụ: Lọc các Số chẵn
Hãy lọc mảng số để chỉ giữ lại các số chẵn.
const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
// Sử dụng filter để chọn các số chẵn
const evenNumbers = numbers.filter(number => number % 2 === 0);
console.log(numbers); // Output: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
console.log(evenNumbers); // Output: [2, 4, 6, 8, 10]
Ví dụ: Lọc Người dùng Hoạt động
Từ mảng người dùng của chúng ta, hãy lọc những người dùng được đánh dấu là hoạt động.
const users = [
{ id: 1, name: 'Alice', isActive: true },
{ id: 2, name: 'Bob', isActive: false },
{ id: 3, name: 'Charlie', isActive: true },
{ id: 4, name: 'David', isActive: false }
];
const activeUsers = users.filter(user => user.isActive);
console.log(activeUsers);
/* Output:
[
{ id: 1, name: 'Alice', isActive: true },
{ id: 3, name: 'Charlie', isActive: true }
]
*/
3. Array.prototype.reduce()
Phương thức reduce()
thực thi một hàm callback “reducer” do người dùng cung cấp trên mỗi phần tử của mảng, theo thứ tự, truyền vào giá trị trả về từ phép tính trên phần tử trước đó. Kết quả cuối cùng của việc chạy reducer trên tất cả các phần tử của mảng là một giá trị duy nhất.
Đây có thể nói là phương thức đa năng nhất trong các phương thức mảng và là nền tảng của nhiều mô hình lập trình hướng chức năng, cho phép bạn “giảm” một mảng thành một giá trị duy nhất (ví dụ: tổng, tích, số đếm, hoặc thậm chí là một đối tượng hoặc mảng mới).
Cú pháp:
array.reduce(callback(accumulator, currentValue[, index[, array]])[, initialValue])
callback
: Hàm được thực thi cho mỗi phần tử.accumulator
: Giá trị kết quả từ lần gọi trước đó của hàm callback. Ở lần gọi đầu tiên, nó làinitialValue
nếu được cung cấp; nếu không, nó là phần tử đầu tiên của mảng.currentValue
: Phần tử hiện tại đang được xử lý.index
(tùy chọn): Chỉ mục của phần tử hiện tại.array
(tùy chọn): Mảng màreduce
đã được gọi trên đó.initialValue
(tùy chọn): Giá trị được sử dụng làm đối số đầu tiên cho lần gọi đầu tiên củacallback
. Nếu không cung cấpinitialValue
, phần tử đầu tiên trong mảng sẽ được sử dụng làm giá trịaccumulator
ban đầu và quá trình lặp bắt đầu từ phần tử thứ hai.
Đặc điểm chính:
- Trả về một giá trị duy nhất (có thể là mảng hoặc đối tượng).
- Mảng gốc không bị thay đổi (tính bất biến).
initialValue
rất quan trọng để có sự rõ ràng và tránh lỗi, đặc biệt với các mảng trống hoặc khi kiểu accumulator khác với kiểu phần tử mảng.
Ví dụ: Tính tổng các Số
Hãy tính tổng tất cả các số trong mảng của chúng ta.
const numbers = [1, 2, 3, 4, 5];
// Sử dụng reduce để tính tổng các số
const sum = numbers.reduce((accumulator, currentValue) => accumulator + currentValue, 0); // 0 là initialValue
console.log(sum); // Output: 15
Giải thích:
- Lần gọi 1:
accumulator
là 0,currentValue
là 1. Trả về 0 + 1 = 1. - Lần gọi 2:
accumulator
là 1,currentValue
là 2. Trả về 1 + 2 = 3. - Lần gọi 3:
accumulator
là 3,currentValue
là 3. Trả về 3 + 3 = 6. - Và cứ tiếp tục như vậy, cho đến khi tính toán được tổng cuối cùng.
Ví dụ: Nhóm các Đối tượng theo một Thuộc tính
Chúng ta có thể sử dụng reduce
để biến đổi một mảng các đối tượng thành một đối tượng mà các giá trị được nhóm theo một thuộc tính cụ thể. Hãy nhóm những người dùng của chúng ta theo trạng thái `isActive` của họ.
const users = [
{ id: 1, name: 'Alice', isActive: true },
{ id: 2, name: 'Bob', isActive: false },
{ id: 3, name: 'Charlie', isActive: true },
{ id: 4, name: 'David', isActive: false }
];
const groupedUsers = users.reduce((acc, user) => {
const status = user.isActive ? 'active' : 'inactive';
if (!acc[status]) {
acc[status] = [];
}
acc[status].push(user);
return acc;
}, {}); // Đối tượng trống {} là initialValue
console.log(groupedUsers);
/* Output:
{
active: [
{ id: 1, name: 'Alice', isActive: true },
{ id: 3, name: 'Charlie', isActive: true }
],
inactive: [
{ id: 2, name: 'Bob', isActive: false },
{ id: 4, name: 'David', isActive: false }
]
}
*/
Ví dụ: Đếm Số lần xuất hiện
Hãy đếm tần suất của mỗi loại trái cây trong một danh sách.
const fruits = ['apple', 'banana', 'apple', 'orange', 'banana', 'apple'];
const fruitCounts = fruits.reduce((acc, fruit) => {
acc[fruit] = (acc[fruit] || 0) + 1;
return acc;
}, {});
console.log(fruitCounts); // Output: { apple: 3, banana: 2, orange: 1 }
4. Array.prototype.forEach()
Mặc dù forEach()
không trả về một mảng mới và thường được coi là mệnh lệnh hơn vì mục đích chính của nó là thực thi một hàm cho mỗi phần tử mảng, nhưng nó vẫn là một phương thức cơ bản đóng vai trò trong các mô hình chức năng, đặc biệt là khi cần có tác dụng phụ hoặc khi lặp mà không cần kết quả đã biến đổi.
Cú pháp:
array.forEach(callback(element[, index[, array]])[, thisArg])
Đặc điểm chính:
- Trả về
undefined
. - Thực thi một hàm được cung cấp một lần cho mỗi phần tử mảng.
- Thường được sử dụng cho các tác dụng phụ, như ghi vào bảng điều khiển hoặc cập nhật các phần tử DOM.
Ví dụ: In từng Phần tử
const messages = ['Hello', 'Functional', 'World'];
messages.forEach(message => console.log(message));
// Output:
// Hello
// Functional
// World
Lưu ý: Đối với các phép biến đổi và lọc, map
và filter
được ưa chuộng hơn vì tính bất biến và bản chất khai báo của chúng. Sử dụng forEach
khi bạn đặc biệt cần thực hiện một hành động cho mỗi mục mà không thu thập kết quả vào một cấu trúc mới.
5. Array.prototype.find()
và Array.prototype.findIndex()
Các phương thức này hữu ích để định vị các phần tử cụ thể trong một mảng.
find()
: Trả về giá trị của phần tử đầu tiên trong mảng được cung cấp thỏa mãn hàm kiểm tra được cung cấp. Nếu không có giá trị nào thỏa mãn hàm kiểm tra,undefined
sẽ được trả về.findIndex()
: Trả về chỉ mục của phần tử đầu tiên trong mảng được cung cấp thỏa mãn hàm kiểm tra được cung cấp. Nếu không, nó trả về -1, cho biết không có phần tử nào vượt qua bài kiểm tra.
Ví dụ: Tìm một Người dùng
const users = [
{ id: 1, name: 'Alice' },
{ id: 2, name: 'Bob' },
{ id: 3, name: 'Charlie' }
];
const bob = users.find(user => user.name === 'Bob');
const bobIndex = users.findIndex(user => user.name === 'Bob');
const nonExistentUser = users.find(user => user.name === 'David');
const nonExistentIndex = users.findIndex(user => user.name === 'David');
console.log(bob); // Output: { id: 2, name: 'Bob' }
console.log(bobIndex); // Output: 1
console.log(nonExistentUser); // Output: undefined
console.log(nonExistentIndex); // Output: -1
6. Array.prototype.some()
và Array.prototype.every()
Các phương thức này kiểm tra xem tất cả các phần tử trong mảng có vượt qua bài kiểm tra được thực hiện bởi hàm được cung cấp hay không.
some()
: Kiểm tra xem ít nhất một phần tử trong mảng có vượt qua bài kiểm tra được thực hiện bởi hàm được cung cấp hay không. Nó trả về một giá trị Boolean.every()
: Kiểm tra xem tất cả các phần tử trong mảng có vượt qua bài kiểm tra được thực hiện bởi hàm được cung cấp hay không. Nó trả về một giá trị Boolean.
Ví dụ: Kiểm tra Trạng thái Người dùng
const users = [
{ id: 1, name: 'Alice', isActive: true },
{ id: 2, name: 'Bob', isActive: false },
{ id: 3, name: 'Charlie', isActive: true }
];
const hasInactiveUser = users.some(user => !user.isActive);
const allAreActive = users.every(user => user.isActive);
console.log(hasInactiveUser); // Output: true (vì Bob không hoạt động)
console.log(allAreActive); // Output: false (vì Bob không hoạt động)
const allUsersActive = users.filter(user => user.isActive).length === users.length;
console.log(allUsersActive); // Output: false
// Cách khác sử dụng every trực tiếp
const allUsersActiveDirect = users.every(user => user.isActive);
console.log(allUsersActiveDirect); // Output: false
Chuỗi các Phương thức Mảng cho các Thao tác Phức tạp
Sức mạnh thực sự của lập trình hướng chức năng với các mảng JavaScript tỏa sáng khi bạn nối chuỗi các phương thức này lại với nhau. Vì hầu hết các phương thức này trả về các mảng mới (ngoại trừ forEach
), bạn có thể liền mạch chuyển đầu ra của một phương thức thành đầu vào của một phương thức khác, tạo ra các đường ống dữ liệu thanh lịch và dễ đọc.
Ví dụ: Tìm Tên Người dùng Hoạt động và Nhân đôi ID của họ
Hãy tìm tất cả người dùng hoạt động, trích xuất tên của họ, sau đó tạo một mảng mới nơi mỗi tên được tiền tố bằng một số đại diện cho chỉ mục của nó trong danh sách *đã lọc*, và ID của họ được nhân đôi.
const users = [
{ id: 1, name: 'Alice', isActive: true },
{ id: 2, name: 'Bob', isActive: false },
{ id: 3, name: 'Charlie', isActive: true },
{ id: 4, name: 'David', isActive: true },
{ id: 5, name: 'Eve', isActive: false }
];
const processedActiveUsers = users
.filter(user => user.isActive) // Chỉ lấy người dùng hoạt động
.map((user, index) => ({ // Biến đổi mỗi người dùng hoạt động
name: `${index + 1}. ${user.name}`,
doubledId: user.id * 2
}));
console.log(processedActiveUsers);
/* Output:
[
{ name: '1. Alice', doubledId: 2 },
{ name: '2. Charlie', doubledId: 6 },
{ name: '3. David', doubledId: 8 }
]
*/
Cách tiếp cận theo chuỗi này là khai báo: chúng ta chỉ định các bước (lọc, sau đó ánh xạ) mà không cần quản lý vòng lặp tường minh. Nó cũng bất biến, vì mỗi bước tạo ra một mảng hoặc đối tượng mới, để lại mảng users
gốc không bị thay đổi.
Tính bất biến trong Thực tế
Lập trình hướng chức năng phụ thuộc nhiều vào tính bất biến. Điều này có nghĩa là thay vì sửa đổi các cấu trúc dữ liệu hiện có, bạn tạo các cấu trúc mới với các thay đổi mong muốn. Các phương thức mảng của JavaScript như map
, filter
và slice
vốn hỗ trợ điều này bằng cách trả về các mảng mới.
Tại sao tính bất biến lại quan trọng?
- Tính dễ dự đoán: Mã trở nên dễ suy luận hơn vì bạn không phải theo dõi các thay đổi đối với trạng thái chia sẻ có thể thay đổi.
- Gỡ lỗi: Khi xảy ra lỗi, việc xác định nguồn gốc của vấn đề sẽ dễ dàng hơn khi dữ liệu không bị sửa đổi bất ngờ.
- Hiệu suất: Trong các ngữ cảnh nhất định (như với các thư viện quản lý trạng thái như Redux hoặc trong React), tính bất biến cho phép phát hiện thay đổi hiệu quả.
- Đồng thời: Cấu trúc dữ liệu bất biến vốn đã an toàn cho luồng, giúp đơn giản hóa lập trình đồng thời.
Khi bạn cần thực hiện một thao tác mà theo cách truyền thống sẽ sửa đổi một mảng (như thêm hoặc xóa một phần tử), bạn có thể đạt được tính bất biến bằng cách sử dụng các phương thức như slice
, cú pháp spread (...
), hoặc bằng cách kết hợp các phương thức chức năng khác.
Ví dụ: Thêm một Phần tử một cách Bất biến
const originalArray = [1, 2, 3];
// Cách mệnh lệnh (sửa đổi originalArray)
// originalArray.push(4);
// Cách chức năng sử dụng cú pháp spread
const newArrayWithPush = [...originalArray, 4];
console.log(originalArray); // Output: [1, 2, 3]
console.log(newArrayWithPush); // Output: [1, 2, 3, 4]
// Cách chức năng sử dụng slice và nối chuỗi (ít phổ biến hơn bây giờ)
const newArrayWithSlice = originalArray.slice(0, originalArray.length).concat(4);
console.log(newArrayWithSlice); // Output: [1, 2, 3, 4]
Ví dụ: Xóa một Phần tử một cách Bất biến
const originalArray = [1, 2, 3, 4, 5];
// Xóa phần tử ở chỉ mục 2 (giá trị 3)
// Cách chức năng sử dụng slice và cú pháp spread
const newArrayAfterSplice = [
...originalArray.slice(0, 2),
...originalArray.slice(3)
];
console.log(originalArray); // Output: [1, 2, 3, 4, 5]
console.log(newArrayAfterSplice); // Output: [1, 2, 4, 5]
// Sử dụng filter để xóa một giá trị cụ thể
const newValueToRemove = 3;
const arrayWithoutValue = originalArray.filter(item => item !== newValueToRemove);
console.log(arrayWithoutValue); // Output: [1, 2, 4, 5]
Các thực hành tốt nhất và Kỹ thuật Nâng cao
Khi bạn đã quen hơn với các phương thức mảng chức năng, hãy xem xét các thực hành này:
- Ưu tiên tính dễ đọc: Mặc dù việc nối chuỗi rất mạnh mẽ, nhưng các chuỗi quá dài có thể khó đọc. Hãy xem xét việc chia các thao tác phức tạp thành các hàm nhỏ hơn, có tên hoặc sử dụng các biến trung gian.
- Hiểu sự Linh hoạt của `reduce`: Hãy nhớ rằng
reduce
có thể xây dựng mảng hoặc đối tượng, không chỉ các giá trị đơn lẻ. Điều này làm cho nó cực kỳ linh hoạt cho các phép biến đổi phức tạp. - Tránh Tác dụng Phụ trong Callbacks: Cố gắng giữ cho các callback
map
,filter
vàreduce
của bạn thuần túy. Nếu bạn cần thực hiện một hành động có tác dụng phụ,forEach
thường là lựa chọn phù hợp hơn. - Sử dụng Arrow Functions: Các arrow function (
=>
) cung cấp cú pháp ngắn gọn cho các hàm callback và xử lý việc ràng buộc `this` khác nhau, thường làm cho chúng trở nên lý tưởng cho các phương thức mảng chức năng. - Cân nhắc Thư viện: Đối với các mô hình lập trình hướng chức năng nâng cao hơn hoặc nếu bạn làm việc nhiều với tính bất biến, các thư viện như Lodash/fp, Ramda hoặc Immutable.js có thể có lợi, mặc dù chúng không hoàn toàn cần thiết để bắt đầu với các thao tác mảng chức năng trong JavaScript hiện đại.
Ví dụ: Cách tiếp cận Chức năng để Tổng hợp Dữ liệu
Hãy tưởng tượng bạn có dữ liệu bán hàng từ các khu vực khác nhau và muốn tính tổng doanh số bán hàng cho mỗi khu vực, sau đó tìm khu vực có doanh số cao nhất.
const salesData = [
{ region: 'North', amount: 100 },
{ region: 'South', amount: 150 },
{ region: 'North', amount: 120 },
{ region: 'East', amount: 200 },
{ region: 'South', amount: 180 },
{ region: 'North', amount: 90 }
];
// 1. Tính tổng doanh số theo khu vực sử dụng reduce
const salesByRegion = salesData.reduce((acc, sale) => {
acc[sale.region] = (acc[sale.region] || 0) + sale.amount;
return acc;
}, {});
// salesByRegion sẽ là: { North: 310, South: 330, East: 200 }
// 2. Chuyển đổi đối tượng tổng hợp thành một mảng các đối tượng để xử lý thêm
const salesArray = Object.keys(salesByRegion).map(region => ({
region: region,
totalAmount: salesByRegion[region]
}));
// salesArray sẽ là: [
// { region: 'North', totalAmount: 310 },
// { region: 'South', totalAmount: 330 },
// { region: 'East', totalAmount: 200 }
// ]
// 3. Tìm khu vực có doanh số cao nhất bằng reduce
const highestSalesRegion = salesArray.reduce((max, current) => {
return current.totalAmount > max.totalAmount ? current : max;
}, { region: '', totalAmount: -Infinity }); // Khởi tạo với một số rất nhỏ
console.log('Sales by Region:', salesByRegion);
console.log('Sales Array:', salesArray);
console.log('Region with Highest Sales:', highestSalesRegion);
/*
Output:
Sales by Region: { North: 310, South: 330, East: 200 }
Sales Array: [
{ region: 'North', totalAmount: 310 },
{ region: 'South', totalAmount: 330 },
{ region: 'East', totalAmount: 200 }
]
Region with Highest Sales: { region: 'South', totalAmount: 330 }
*/
Kết luận
Lập trình hướng chức năng với các mảng JavaScript không chỉ là một lựa chọn về phong cách; đó là một cách mạnh mẽ để viết mã sạch hơn, có thể dự đoán và mạnh mẽ hơn. Bằng cách áp dụng các phương thức như map
, filter
và reduce
, bạn có thể biến đổi, truy vấn và tổng hợp dữ liệu của mình một cách hiệu quả đồng thời tuân thủ các nguyên tắc cốt lõi của lập trình hướng chức năng, đặc biệt là tính bất biến và các hàm thuần túy.
Khi bạn tiếp tục hành trình phát triển JavaScript của mình, việc tích hợp các mô hình chức năng này vào quy trình làm việc hàng ngày của bạn chắc chắn sẽ dẫn đến các ứng dụng dễ bảo trì và có khả năng mở rộng hơn. Hãy bắt đầu bằng cách thử nghiệm với các phương thức mảng này trong các dự án của bạn và bạn sẽ sớm nhận ra giá trị to lớn của chúng.