18+ kĩ thuật rút gọn code Javascript của bạn
1. Toán tử 3 ngôi (Ternary Operator) Sử dụng khi cần rút ngắn đoạn if..else thành 1 dòng. Thay vì const x = 100; let result; if (x < 1000) { result = "nhỏ hơn 1000"; } else { result = "lớn hơn hoặc bằng 1000"; } thì const x = 100; const result = (x < 1000) ? "nhỏ hơn 1000" : ...
1. Toán tử 3 ngôi (Ternary Operator)
Sử dụng khi cần rút ngắn đoạn if..else thành 1 dòng. Thay vì
const x = 100; let result; if (x < 1000) { result = "nhỏ hơn 1000"; } else { result = "lớn hơn hoặc bằng 1000"; }
thì
const x = 100; const result = (x < 1000) ? "nhỏ hơn 1000" : "lớn hơn hoặc bằng 1000";
2. Shorthand Evaluate
Khi gán giá trị của biến cho biến khác, chúng ta thường muốn đảm bảo rằng giá trị biến đó không null, không undefinded hoặc rỗng, vì vậy mà cần phải viết một loạt điều kiện để kiểm tra:
let variable2; if (variable1 !== null || variable1 !== undefined || variable1 !== ') { variable2 = variable1; } else { variable2 = ""; }
Có thể rút ngắn gọn thành:
const variable2 = variable1 || "";
3. Khai báo biến
Khai báo biến tốt nhất là khai báo khi bắt đầu 1 function. Cách viết sau sẽ giúp bạn tiết kiệm được thời gian cũng như số dòng khi khai báo: Thay vì
let x; let y; let z = 3;
Thay bằng:
let x, y, z = 3;
4. Bỏ qua toán tử so sánh bằng trong If
Khi điều kiện là so sánh bằng, trong trường hợp biến đã được định nghĩa trước và quy ước kiểu là Boolean, ta có thể bỏ qua toán tử so sánh == hoặc ===
if (isTurnOn === true)
Thay bằng
if (isTurnOn)
Hoặc nếu trong trường hợp giá trị cần là false
if (!isTurnOn)
5. Vòng lặp For
Tip sau sẽ thực sự hữu ích trong trường hợp bạn muốn sử dụng Js thuần mà không phụ thuộc vào thư viện bên thứ 3 như Lodash hay jQuery. Thay vì:
for (let i = 0; i < sampleArr.length; i++)
Thành
for (let item in sampleArr)
6. Decimal base exponents
Để biểu diễn số hàng triệu, hàng tỉ, thay vì viết một đống con số 0, ta có thể viết thành kiểu là số thực phẩy động (float type). Thay vì
for (let i = 0; i < 100000; i++) {}
thành
for (let i = 0; i < 1e5; i++) {} # giá trị các biểu thức sau đều là true 1e0 === 1; 1e1 === 10; 1e2 === 100; 1e3 === 1000; 1e4 === 10000; 1e5 === 100000;
7. Object property
ES6 cung cấp cho ta khả năng gán property cho object dễ dàng hơn. Nếu tên key trùng luôn với tên biến, thì, thay vì:
const x = 1, y = 2; const obj = { x: x, y: y };
có thể viết lại thành
const x = 1, y = 2; const obj = { x, y };
8. Rút gọn khai báo function
Kiểu khai báo function cũ thì dễ đọc dễ viết, nhưng nó sẽ trở nên rối khi nằm chung với những lời gọi hàm khác. Ví dụ thay vì
function sayHello(name) { console.log('Hello', name); } setTimeout(function() { console.log('Loaded') }, 2000); list.forEach(function(item) { console.log(item); });
có thể dùng cú pháp arrow để khai báo function (arrow function):
sayHello = name => console.log('Hello', name); setTimeout(() => console.log('Loaded'), 2000); list.forEach(item => console.log(item));
9. Implicit Return
Thường ta sử dụng return để trả về kết quả cuối của function. Tuy nhiên trong arrow function thì việc return kết quả là implicit: Thay vì:
function getValue(ratio) { return ratio * 6.9; }
có thể ngắn gọn hơn:
getValue = ratio => ratio * 6.9
10. Giá trị default cho params của function
Có thể sử dụng if để gán giá trị default cho params của function trong trường hợp cần thiết. Tuy nhiên từ ES6, bạn có thể gán giá trị default cho params ngay khi khai báo hàm. Thay vì:
function getValue(a, b, c) { if (a === undefined) a = 3; if (b === undefined) b = 4; return a * b + c; }
thành:
getValue = (a, b = 3, c = 4 ) => (a * b + c);
11. Template Literals
Mệt mỏi vì dùng toán tử + để cộng biến nối chuỗi ? Từ ES6 trở đi, ta được cung cấp một giải pháp ngắn gọn và trực quan hơn bằng cách sử dụng ${} trong cặp nháy backtick ```:
const welcome = 'You have logged in as ' + first + ' ' + last + '.'
thay bằng:
const welcome = `You have logged in as ${first} ${last} .`;
12. Destructuring Assignment
Nếu đã làm việc với các framework js, hẳn ta không lạ gì việc truyền các data dưới dạng object giữa các component với nhau. Khi data object được truyền tới nơi thì ta cần unpack nó.
const action = require('lib/action') const service = require('lib/service') const form = this.props.form; const errors = this.props.errors; const entity = this.props.entity; const controller = this.props.controller; const component = this.props.component;
Đoạn trên có thể rút gọn:
import { action, service } from 'lib'; const { form, errors, entity, controller, component } = this.props;
13. Multi-line string
Để gán giá trị cho một biến là một chuối nhiều dòng, thay vì:
const lorem = 'Lorem ipsum dolor sit amet, consectetur ' + 'adipisicing elit, sed do eiusmod tempor incididunt ' + 'ut labore et dolore magna aliqua. Ut enim ad minim ' + 'veniam, quis nostrud exercitation ullamco laboris ' + 'nisi ut aliquip ex ea commodo consequat. Duis aute ' + 'irure dolor in reprehenderit in voluptate velit esse. '
đơn giản ta wrap tất cả text trong cặp backtick ```
const lorem = `Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse.`
14. Spread Operator
Trong ES6 spec có giới thiệu một chức năng mới khá là lợi hại mà không phải ai cũng hay dùng, đó là Spread Operator. Chức năng này không có gì là xa lạ với các ngôn ngữ khác, trong thế giới Ruby thì nó tương đương splat operator. Spread Operator cho phép chuyển đổi một chuỗi thành nhiều argument (trong trường hợp gọi với hàm) hoặc thành nhiều phần tử (cho array). Thêm vào nữa nó cũng cho phép làm nhiệm vụ destructure. Operator này có syntax là 3 dấu chấm ...
// joining arrays const odd = [1, 3, 5]; const nums = [2 ,4 , 6].concat(odd); // cloning arrays const arr = [1, 2, 3, 4]; const arr2 = arr.slice()
Ngắn gọn hơn:
// joining arrays const odd = [1, 3, 5 ]; const nums = [2 ,4 , 6, ...odd]; // cloning arrays const arr = [1, 2, 3, 4]; const arr2 = [...arr];
Không như hàm concat(), dùng spread operator, ta có thể chèn 1 array vào vị trí bất kì nào trong array cần chèn tới:
const odd = [1, 3, 5 ]; const nums = [2, ...odd, 4 , 6];
- Spread operator trong gọi hàm: Nếu có 1 hàm như sau:
function sayHello(firstName, lastName, nickName) {}
vả array chứa thông tin sẽ dùng làm tham số truyền vào:
var names = ['Duy', 'Tăng', 'buffet']
để truyền tham số vào hàm thì cần làm như sau:
sayHello(names[0], names[1], names[2])
hoặc có cách khác hay hơn nếu chúng ta ko biết rõ biến names dài bao nhiêu với Function.prototype.apply
sayHello.apply(null, names)
Với ES6, ta có thể áp dụng spread operator như sau:
sayHello(...names)
15. Ràng buộc params
Default thì Javascript sẽ set parameters là undefined nếu không có value được truyền vào function. Ở một số ngôn ngữ khác, nó ném ra exception hoặc warning nếu không truyền đủ params. Để làm điều tương tự với Javascript, ta có thể xét ràng buộc:
function sample(param1) { if (param1 === undefined) { throw new Error('Thiếu tham số!'); } return param1; }
Hoặc viết ngắn gọn hơn bằng cách sử dụng Mandatory parameter
mandatory = () => { throw new Error('Thiếu tham số!'); } sample = (param1 = mandatory()) => param1
16. Array.find
Nếu từng phải viết hàm tìm kiếm bằng Javascript thuần, hẳn ta sẽ nghĩ ngay đến việc dùng vòng lặp for lặp qua từng phần tử và kiểm tra điều kiện tìm kiếm. Tuy nhiên trong ES6, function find của array được giới thiệu, giúp cho việc tìm phần tử trong array ngắn gọn hơn. Thay vì
const employees = [ { name: 'Emp A', age: 25 }, { name: 'Emp B', age: 28 }, { name: 'Emp C', age: 35 } ] function findEmp(name) { for(let i = 0; i<employees.length; ++i) { if(employees[i].name === name) { return employees[i]; } } } const name = 'Emp A' emp = findEmp(name)
thành
const name = 'Emp A' emp = employees.find(item => item.name === name)
17. Object [key]
Để get property của object trong JS ngoài cách Obj.prop, còn có thể viết Obj['prop']. Nhìn qua thì dùng cả 2 cách đều cho kết quả như nhau. Tuy nhiên để viết được những đoạn code có thể tái sử dụng, thì cần sử dụng cách thứ 2: Xem xét ví dụ 1 hàm validation:
function validate(fullName) { if(!fullName.firstName) return false; if(!fullName.lastName) return false; return true; } console.log(validate({firstName:'Duy',lastName:'Buffet'})); // true
Đoạn code trên hoạt động rất tốt, tuy nhiên nó lại chỉ áp dụng được với duy nhất trường hợp object có đúng 2 property firstName, lastName. Để có thể áp dụng được với những object có property khác, validation rule khác thì ta cần viết tổng quát hơn:
const rule = { firstName: { required:true }, lastName: { required:true } } const validate = (rule, values) => { for(prop in rule) { if(rule[prop].required) { if(!values[prop]) { return false; } } } return true; } console.log(validate(rule, {firstName:'Duy'})); // false console.log(validate(rule, {firstName:'Duy',lastName:'Buffet'})); // true
Giờ thì hàm validate đã tổng quát hơn và có khả năng tái sử dụng nhờ cách gọi property Obj['prop']
18. Toán tử bitwise NOT Double
Double bitwise NOT (2 lần phủ định) có thể dùng thay thế cho hàm làm tròn xuống Math.floor(). Ưu điểm của các phép toán bitwise đó là nó thực hiện tác vụ tương tự cho hiệu suất cao hơn do làm việc trực tiếp với binary. Cách viết dài:
Math.floor(6.9) === 6 // true
Ngắn gọn:
~~6.9 === 6 // true
Trên đây bài viết đã tổng hợp một số kĩ thuật khiến code Javascript trở nên ngắn gọn, rõ ràng hơn. Hi vọng bài viết sẽ giúp được phần nào các bạn trong quá trình làm việc với Javascript.
Nguồn tham khảo
- ES6
- Sitepoint