Với kinh nghiệm của bản thân khi làm một lập trình viên frontend, tôi thường xây dựng những thói quen riêng khi viết code để giúp đoạn mã trở nên linh hoạt và nâng cao khả năng đọc cũng như bảo trì mã.
Đây hoàn toàn là những mẹo rất đơn giản nhưng vô cũng hữu ích mà tôi muốn chia sẻ để bạn hoàn toàn có thể hiểu ngay từ những cái nhìn đầu tiên.
Kỹ thuật 1: Giảm số lượng câu lệnh if-else
Mỗi khi viết mã gì đó có sử dụng nhiều hơn 2 lần if-else
chúng ta cần phải cân nhắc xem có cách nào viết mã tối ưu hơn không. Ví dụ đơn giản như sau:
function getPrice(item) {
if (item === 'iPHONE') return 1.0;
else if (item === 'Samsung') return 0.5;
else if (item === 'Xiaomi') return 0.75;
// more ...
}
Trong ví dụ này tôi đang viết một hàm lấy giá của các hãng điện thoại, nếu như tôi muốn thêm giá của điện thoại oppo, tôi sẽ cần phải thêm một nhánh if-else
, hoặc tôi muốn sửa đổi giá của chiếc điện thoại Xiaomi tôi sẽ phải mất công đi tìm vị trí của chiếc điện thoại xiaomi trong thân hàm của mình.
Việc viết mã như trên có thể khiến cho mã dễ gặp những lỗi như dài dòng, khó đọc, khó tìm kiếm và mở rộng.
Nhưng đừng lo tôi sẽ chỉ cho bạn cách viết đúng mà không vi phạm nguyên tắc DRY. Chúng ta sẽ sử dụng một object để lưu lại giá cho các sản phẩm thay vì sử dụng một chuỗi if-else-if
function getPrice(item) {
const prices = {
'iPHONE': 1.0,
'Samsung': 0.5,
'Xiaomi': 0.75,
'Oppo': 0.6
};
return prices[item] || 0; // Trả về giá trị hoặc 0 nếu không có sản phẩm
}
Ví dụ cải tiến trên chúng ta đã có thể đọc mã một cách clear hơn, hay khi muốn thay đổi một giá của một sản phẩm chúng ta không cần phải thay đổi logic cốt lõi của hàm getPrice().
Kỹ thuật 2: Kỹ thuật Pipelining giảm số vòng lặp không cần thiết
const phones = [
{ name: 'Apple', group: 1 },
{ name: 'Samsung', group: 2 },
{ name: 'Xiaomi', group: 1 },
// more items...
];
const group1 = [];
for (let i = 0; i < phones .length; i++) {
if (phones[i].group === 1) {
group1.push(phones [i].name);
}
}
Đây là một cách làm truyền thống, bạn có thể dùng vòng lặp for để lặp qua từng phần tử trong mảng và kiểm tra xem phần tử nào đáp ứng điều kiện sau đó thêm nó vào mảng kết quả.
Mặc dù phương pháp trên không sai, tuy nhiên việc viết mã như vậy có thể khiến cho mã dài dòng và khó đọc hơn. Thay vào đó chúng ta có thể sử dụng các hàm thông dụng như filter
và map
để giúp cho đoạn mã ngắn gọn và tăng cường về mặt ngữ nghĩa.
const group1 = phones
.filter(phone => phone.group === 1)
.map(phone => phone.name);
Kỹ thuật 3: Sử dụng find để thay thế các vòng lặp trùng lặp
Tiếp tục với ví dụ về mảng điện thoại bên trên. Khi đó việc sử dụng find
cho thấy sự tiện lợi rõ ràng
const phones = [
{ name: 'Apple', group: 1 },
{ name: 'Samsung', group: 2 },
{ name: 'Xiaomi', group: 1 },
// more items...
];
// Tìm phần tử đầu tiên có group === 1
const phoneInGroup1 = phones.find(phone => phone.group === 1);
console.log(phoneInGroup1); // Kết quả: { name: 'Apple', group: 1 }
Phương pháp tìm này cho phép bạn nhanh chóng xác định vị trí phần tử đầu tiên trong mảng có thoả mãn điều kiện được cung cấp giúp code clear hơn rất nhiều so với việc dùng các vòng lặp truyền thống.
Kỹ thuật 4: Sử dụng includes thay thế các vòng lặp dư thừa
Khi chúng ta cần kiểm tra xem một mảng có chứa giá trị cụ thể hay không, sử dụng includes
có thể làm đơn giản đoạn mã của bạn thay vì lặp qua mảng để kiểm tra sự tồn tại của phần tử.
Ví dụ:
const fruits = ['Apple', 'Banana', 'Carrot'];
let hasBanana = false;
for (let i = 0; i < fruits.length; i++) {
if (fruits[i] === 'Banana') {
hasBanana = true;
break;
}
}
Bạn chỉ cần sử dụng includes
:
const hasBanana = fruits.includes('Banana');
Phương pháp này cung cấp một giải pháp tinh tế cho quá trình rườm rà hơn khi sử dụng các vòng lặp truyền thống.
Tính năng này đặc biệt hữu ích khi xử lý mảng mà bạn thường xuyên cần kiểm tra.
Kỹ thuật 5: Sử dụng biến trả về kết quả duy nhất
Theo như mình được biết đặc biệt là trong các hàm nhỏ gọn, chúng ta có thể sử dụng tên biến nhất quán cho kết quả trả về. Điều này làm rõ giá trị về đến từ đâu và cung cấp quy ước đặt tên biến chuẩn mà nếu người khác đọc code của bạn họ có thể dễ dàng nhận ra.
function calculateTotal(items) {
let result = 0;
for (let i = 0; i < items.length; i++) {
result += items[i].price;
}
return result;
}
Kỹ thuật 6: Duy trì tính toàn vẹn của đối tượng
Trong lúc thao tác với dữ liệu JSON trả về từ backend, chúng ta thường xử lý các thuộc tính cụ thể riêng lẻ trong một key-value. Điều này càng rõ ràng hơn khi đôi khi chúng ta có những case chỉ dùng đến vài thuộc tính. Nhiều lập trình viên có xu hướng chỉ trích xuất các thuộc tính cần thiết cho các hoạt động, đây là phương pháp đầu tiên người ta nghĩ đến, tuy nhiên đây là một cách làm thực tế và không lâu dài.
Khi không chắc chắn rằng liệu một hàm có cần thêm các phụ thuộc sau này hay không, việc duy trì tính toàn vẹn của toàn bộ đối tượng là điều nên làm. Ví dụ một function component có thể sử dụng icon
và content
nhưng có thể sau này title
hoặc date
có thể được sử dụng. Việc truyền toàn bộ đối tượng vào function component thay vì thuộc tính riêng lẻ không chỉ làm giảm độ dài của danh sách props mà còn tăng cường khả năng đọc và linh hoạt của mã
// Trích xuất từng thuộc tính riêng lẻ
function Card({ icon, content }) {
return (
<div>
<img src={icon} alt="icon" />
<p>{content}</p>
</div>
);
}
// Sử dụng
const data = { icon: 'icon.png', content: 'Hello world', title: 'Welcome' };
<Card icon={data.icon} content={data.content} />;
// Duy trì toàn vẹn của đối tượng
function Card(props) {
const { icon, content } = props;
return (
<div>
<img src={icon} alt="icon" />
<p>{content}</p>
</div>
);
}
// Sử dụng
const data = { icon: 'icon.png', content: 'Hello world', title: 'Welcome' };
<Card {...data} />;
🌟 Kết luận cuối cùng
Các kỹ thuật viết mã JS ở trên có thể cải thiện hiệu suất chất lượng cho đoạn code của bạn, giúp chúng dễ dàng đọc và maintain lâu dài. Vì vậy hãy thử những tip đơn giản này trong dự án và trải nghiệm trực tiếp những cải tiến trên nhé. Chúc bạn code vui vẻ !!!
Top comments (0)