Series JavaScript sida – Cùng làm quen và “chịch”, nhầm… nghịch ES6
Dạo gần đây mình đi làm thêm, project hiện tại có sử dụng React với cả ES6 – chuẩn Javascript mới. Do mấy bài viết trước mình chê JavaScript sida nhiều thấy cũng tội, hôm nay viết một bài nói tốt cho nó một tí để đổi gió nhé. Phiên bản JavaScript hiện tại chúng ta đang sử dụng dựa trên chuẩn ...
Dạo gần đây mình đi làm thêm, project hiện tại có sử dụng React với cả ES6 – chuẩn Javascript mới. Do mấy bài viết trước mình chê JavaScript sida nhiều thấy cũng tội, hôm nay viết một bài nói tốt cho nó một tí để đổi gió nhé.
Phiên bản JavaScript hiện tại chúng ta đang sử dụng dựa trên chuẩn ECMAScript 5 (ES5). Hiện tại, JavaScript được sử dụng ngày càng nhiều, từ front-end cho đến back-end, điều này đòi hỏi sự cải tiến trong JavaScript (Nghĩ cũng đúng, cái ngôn ngữ sida thế mà code mấy hệ thống to to, code phức tạp thì để lâu chả banh chành ra à !!). Đó là lý do chuẩn ECMAScript 6 (ES6) ra đời, cung cấp 1 số tính năng mới cho JavaScript, đồng thời giúp code trở nên tường minh và dễ viết hơn.
Trong phạm vi bài viết, mình sẽ giới thiệu một số tính năng mới của ES6 và mổ xẻ so sánh nó với ES5 (Mình chỉ giới thiệu 1 số tính năng hay thôi nhé, các bạn tham khảo nguồn dưới cuối bài để tìm hiểu thêm). Để chạy được ES6 phải ta setup hoặc add thư viện hơi rắc rối, biết các bạn lười mình đã chuẩn bị sẵn 1 link jsfiddle hỗ trợ ES6 cho các bạn, các bạn cứ vào mà nghịch code ES6 thoải mái thôi: .
Tính năng nào cảm thấy hay mình sẽ đặt lên đầu tiên nhé. Bắt đầu nào!!
1. Arrow (Lambda Expression)
Ở ES6, thay vì khai báo function như kiểu thông thường, ta đã có thể sử dụng =>. Cách khai báo này tương tự như Lambda Expression trong C#, giúp cho code tường minh và ngắn gọn hơn rất rất nhiều.
var numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; // Giả sử ta muốn tìm các số chẵn // Cách viết cũ var odd = numbers.filter(function(n) { return n % 2 == 1 }); console.log(odd); // Với arrow odd = numbers.filter(n => n % 2 == 1); console.log(odd);
Ngoài ra, nhờ có arrow, ta không còn bị tình trạng this bị bind nhầm như trước kia nữa.
var person = { firstName: 'Hoang', friends : ['Minh', 'Sang', 'Khoa', 'Hoang'], showFriend: function() { this.friends.forEach(function(fr) { // Với cách viết cũ, this ở đây sẽ là object window, không phải person console.log(this.firstName + ' have a friend named ' + fr); }); // Ta sử dụng arrow, this vẫn là object person this.friends.forEach(fr => console.log(this.firstName + ' have a friend named ' + fr)); } };
2. Default parameter, destructuring, spread operator
Default parameter đã có từ lâu trong C#, giờ JavaScript cũng đã có nhưng… Java vẫn chưa có. Nhờ default parameter, ta có thể xác định giá trị mặc định của tham số truyền vào.
// Cách cũ, phải check tham số truyền vào rồi xác định giá trị function multiply(a, b) { var b = typeof b !== 'undefined' ? b : 1; return a*b; } // Với ES6, chỉ cần sử dụng dấu = function multiply(a, b = 1) { return a*b; } multiply(5); // 5
Destructuring cũng là một tính năng khá hay, nó cho phép ta "phân rã" các phần tử trong 1 array hoặc 1 object
// Với array var foo = ["one", "two", "three"]; // Cách cũ var one = foo[0]; var two = foo[1]; var three = foo[2]; // Dùng destructuring var [one, two, three] = foo; // Với object var obj = {firstName:'Hoang', lastName:'Pham'}; // Cách cũ var firstName = obj.firstName; var lastName = obj.lastName; // Dùng destructuring var {firstName, lastName} = obj; // Nếu muốn lấy tên biến khác tên field của object var {firstName : fn, lastName : ln} = obj; //fn: Hoang, ln: Pham
Một tính năng mới khác mà mình cảm thấy khá thú vị đó là spread operator, tính năng này cho phép chuyển đổi qua lại giữa 1 array và danh sách các params. Nghe hơi khó hiểu nhỉ, nhìn code là hiểu ngay.
function f(x, ...y) { // y ở đây là array, chứa ["hello", true, false] return x * y.length; } f(3, "hello", true, falser) == 9; // Cách gọi này tương tự với f(3, ["hello", true, false]) function f(x, y, z) { return x + y + z; } f(...[1,2,3]) == 6; // Cách gọi này tương tự với f(1, 2, 3);
3. Cải tiến syntax class và object
Lần trước, mình đã chửi thằng JavaScript sida vì nó chẳng có class gì sất, mà phải dùng prototype. Chắc nghe chửi nhiều quá nên các bác cũng sợ, giờ đã phải thêm class vào ES6. Trong ES6, class có hỗ trợ constructor, get/set, việc kế thừa cũng rất dễ thực hiện bằng từ khóa extends.
class Animal { constructor(name) { this.name = name; } speak() { console.log(this.name + ' makes a noise.'); } } class Dog extends Animal { speak() { console.log(this.name + ' barks.'); } }
Với cách khai báo object mới, ta có thể viết code một cách ngắn gọn và rõ ràng hơn nhiều. Mình là mình lười code lắm, viết code càng ít mình càng khoái.
var firstName = 'Hoang'; var lastName = 'Pham'; // Khai báo object kiểu cũ var obj = { firstName: firstName, lastName: lastName, showName: function() { console.log(this.firstName + ' ' + this.lastName) } }; // Khai báo kiểu mới, ngắn gọn hơn // Không cần lặp lại tên biến hay function var obj = { firstName, lastName, showName() { console.log(this.firstName + ' ' + this.lastName) } };
4. Iterator
Ngày xưa, để duyệt qua từng phần tử trong một mảng, ta phải sử dụng hàm for, chạy index từ 0 tới cuối mảng. Về sau đỡ hơn, ta có thể sử dụng hàm forEach. _Tuy nhiên nhiều người lại thấy cú pháp hàm _forEach hơi lạ, không được tự nhiên cho lắm. Trong ES6, ta đã có thêm for… of để duyệt từng phần tử trong một mảng (Đừng nhầm với for…in, để duyệt các trường trong 1 object nhé).
var numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; // Cách cũ, duyệt từ đầu for(var i = 0; i< numbers.length; i ++) { console.log(number[i]); } // Dùng forEach numbers.forEach(function(number) { console.log(number); }) // Dùng for...of, dễ viết dễ đọc for(var number of numbers) console.log(number);
5. Template String
Chức năng này khá giống chức năng string interpolation trong C# 6.0. Trước đây, JavaScript không có string.format, do đó ta phải cộng chuỗi bằng tay rất cực. Giờ đây, sử dụng template string, ta không cần phải mất công cộng chuỗi nữa, code rõ ràng hơn nhiều.
var name = "Bob", time = "today"; // Cách cũ console.log("Hello " + name + " how are you " + time + " ?"); // Dùng string interpolation, để ý dấu ` console.log(`Hello ${name}, how are you ${time}?`);
6. Map và Set
Nhắc lại một chút kiến thức cơ bản: Map là cấu trúc dữ liệu cho phép ta lưu dữ liệu dưới dạng Key-Value, Set là một mảng mà trong đó không có phần tử nào trùng nhau (Bạn nào quên thì lật sách Cấu trúc dữ liệu và thuật toán ra xem lại nhé). Giờ ES6 đã bổ sung thêm 2 cấu trúc dữ liệu này, giúp việc code được dễ dàng hơn.
// Sets var s = new Set(); s.add("hello").add("goodbye").add("hello"); s.size === 2; s.has("hello") === true; // Maps var m = new Map(); m.set("hello", 42); m.set(s, 34); m.get(s) == 34;
7. Promise
Promise là một khái niệm khá hay, giúp cho việc viết code asynchonous (bất đồng bộ) dễ dàng hơn. Promise được sử dụng trong rất nhiều thư viện như jQuery, AngularJS. Lần khác có thời gian mình sẽ viết bài nói rõ hơn về khái niệm này, còn hiện tại các bạn qua blog của bạn mình xem tạm nhé: Tìm hiểu về promise.
// Code from: http://www.html5rocks.com/en/tutorials/es6/promises/ var promise = new Promise(function(resolve, reject) { // do a thing, possibly async, then… if (true) { resolve("Stuff worked!"); } else { reject(Error("It broke")); } }); promise.then(function(result) { console.log(result); // "Stuff worked!" }, function(err) { console.log(err); // Error: "It broke" });
Có thể thấy, ES6 đã làm JavaScript bớt sida hơn nhiều. Tuy nhiên, ES6 vẫn còn một khuyết điểm, đó là nó chưa được hỗ trợ hầu hết các trình duyệt. IE và Chrome không thể chạy trực tiếp ES6 được, Firefox thì chỉ chạy được 1 số tính năng: https://kangax.github.io/compat-table/es6/.
Dù vậy, hiện tại nhiều công ty đã áp dụng ES6 vào code. Lập trình viên viết code ES6 như thường, sau đó *sử dụng babel/traceur *để dịch code EcmaScript 6 sang EcmaScript 5 (Project hiện tại của mình cũng vậy, cứ viết code ES6 xong nó tự build ra JavaScript ES5, khá sướng). Trong tương lai vài năm nữa, khi các trình duyệt đã hỗ trợ đầy đủ, ta có thể viết ES6 và chạy thẳng trên trình duyệt luôn.
Trong phạm vi bài viết, mình không thể nêu hết toàn bộ các cải tiến của ES6 được. Bạn nào có hứng thú có thể tham khảo thêm ở một số nguồn dưới đây:
Bản gốc: Blog Tôi đi code dạo.