10 tính năng mới tuyệt vời của ECMAScript 6

Ngoc Huynh

Bạn đã biết rằng JavaScript (cùng với Jscript và ActionScript) là một hệ thống xử lý đặc tả ngôn ngữ kịch bản phía khách hàng đa năng có tên gọi là ECMAScript phải không? Để làm cho định nghĩa này hấp dẫn hơn một chút, chúng ta có thể nói rằng ECMAScript (hay chính thức ECMA-262) là tiêu chuẩn để định rõ cách chúng ta sử dụng JavaScript, và những gì mà chúng ta có thể thực hiện cùng với nó.

Phiên bản mới của ECMAScript là ECMASScript 2015 (hay ES6) có lẽ là bản cập nhật quan trọng nhất kể từ phiên bản đầu tiên vào năm 1997. Mục tiêu chính của ES6 là nhằm cung cấp sự hỗ trợ tốt nhất dành cho việc tạo ra các ứng dụng và thư viện (library) với quy mô lớn hơn. Điều này có nghĩa là cú pháp hoàn thiện hơn, các shortcut mới để lập trình dễ dàng hơn, và còn có các phương pháp, keyword (từ khóa), kiểu dữ liệu mới và nhiều cải tiến khác.

Tài liệu của ES6 thì bao quát, nếu bạn muốn tìm hiểu nhiều hơn, bạn có thể download toàn bộ các đặc điểm kỹ thuật từ website của ECMA International. Trong khuôn khổ bài viết hôm nay, chúng tôi sẽ giới thiệu 10 tính năng hay nhất, dù cho ES6 có rất nhiều tính năng mới. Nếu bạn muốn thực nghiệm với ES6, thì ES6 Fiddle là một nơi thích hợp để làm điều này, và bạn cũng có thể tìm thấy một số các code snippet mẫu tại đây.

Hỗ trợ dành cho ECMAScript 6

Các nhà cung cấp trình duyệt đã từng bước thêm hỗ trợ dành cho các tính năng của ECMAScript 6. Bạn có thể tìm thấy bảng tương thích tại đây về hỗ trợ trình duyệt và trình biên dịch đối với các tính năng mới.

Nếu bạn quan tâm đến hỗ trợ ES6 trong Node.js, bạn có thể tham khảo thêm các tài liệu tại đây.

Mặc dù không phải tất cả các tính năng hiện tại đều được hỗ trợ, nhưng chúng ta có thể sử dụng các bộ phiên dịch (transpiler) chẳng hạn như Babel để phiên dịch lập trình ES6 sang ES5. Ngoài ra còn có Grunt plugin dành cho Babel, các ES6 plugin dành cho Grunt, và Gulp-Babel plugin để chúng ta có thể lựa chọn.

Hiện tại chúng ta có thể sử dụng các tính năng và cú pháp đã được cải tiến mà không cần phải lo về khả năng tương thích.

1. Từ khóa let mới

ES6 giới thiệu từ khóa “let” mới, cho phép chúng ta khai báo các local variable trong phạm vi của một block, chẳng hạn như một statement (câu lệnh), expression, hoặc một inner function. Ví dụ như chúng ta có thể khai báo vòng lặp (loop) “for” theo cách sau đây, sau đó tái sử dụng tên biến tương tự bên trong câu lệnh “if” tiếp theo:

for (let i = 0; i < myArray.length; i++) {

// Do something inside the block

}

if (x > 0 && x != y) {

// We reuse “i”
let i = x * y
}

Với việc sử dụng từ khóa “let” sẽ tạo ra một lập trình sạch hơn và khả dụng hơn. Sự khác nhau giữa letvar là về phạm vi, ví dụ như: một local variable được xác định bởi từ khóa var có thể được sử dụng trong toàn bộ hàm xây quanh, trong khi các biến được xác định bằng từ khóa let chỉ hoạt động trong block riêng. Let cũng có thể được sử dụng rộng rãi, trong trường hợp này nó vận hành theo cùng một cách như var. Dĩ nhiên, trong ES6 chúng ta vẫn có thể sử dụng var nếu muốn.

2. Từ khóa const mới

Từ khóa const mới có thể giúp khai báo các hằng (constants), cũng còn được biết đến với tên gọi là các biến bất biến, mà chúng ta không thể gán lại bằng một nội dung mới.

const MY_CONST = 12;
console.log(MY_CONST);
// 12

MY_CONST = 16;
// Silent error, as we cannot reassign a new value to a constant

Các biến bất biến thì không hoàn toàn bất biến trong ECMAScript 6, như thể là một hằng nắm giữ một đối tượng, sau đó chúng ta có thể thay đổi giá trị của các properties (thuộc tính) và các methods (phương thức).

const MY_CONSTANT = {myProperty: 6};
console.log(MY_CONSTANT.myProperty);
// 6

MY_CONSTANT.myProperty = 18;
console.log(MY_CONSTANT.myProperty);
// 18

const OTHER_CONSTANT = [12, 14, 16];
console.log(OTHER_CONSTANT[0]);
// 12

OTHER_CONSTANT[0] = 22;
console.log(OTHER_CONSTANT[0]);
// 22

Chúng ta vẫn không thể trực tiếp gán một giá trị mới cho đối tượng MY_CONSTANT trong code snippet ở phía trên, điều này có nghĩa là chúng ta không thể thay đổi tên của các property và methods, và cũng không thể thêm mới hay xóa cái đang tồn tại, do đó chúng ta không thể thực hiện điều sau đây:

MY_CONSTANT = {newProperty: 18};
console.log(MY_CONSTANT.newProperty);
// error

3. Arrow function (Hàm mũi tên)

ECMAScript 6 làm đơn giản hóa cách chúng ta viết các anonymous functions (hàm nặc danh), khi chúng ta có thể hoàn toàn bỏ qua từ khóa “function”. Chúng ta chỉ cần sử dụng cú pháp mới cho các arrow function, đặt tên sau ký hiệu mũi tên =>.

// 1. One parameter in ES6
let sum = (a, b) => a + b;

// in ES5
var sum = function(a, b) {
return a + b;
};

// 2. Without parameters in ES6
let randomNum = () => Math.random();

// in ES5
var randomNum = function() {
return Math.random();
};

// 3. Without return in ES6
let message = (name) => alert(“Hi ” + name + “!”);

// in ES5
var message = function(yourName) {
alert(“Hi ” + yourName + “!”);
};

Bên cạnh đó còn có sự khác nhau quan trọng giữa regular function (hàm chính quy) và arrow function, đó là arrow function không nhận giá trị “this” một cách tự động như các hàm được xác định bằng từ khóa “function”. Về phương diện từ vựng, Arrow functions kết giá trị “this” vào phạm vi hiện tại. Điều này có nghĩa là chúng ta có thể dễ dàng tái sử dụng từ khóa “this” trong inner function. Ở ES5, điều đó chỉ có thể thực hiện cùng với hack sau đây:

// ES5 Hack to use the “this” keyword in an inner function
{

addAll: function addAll(pieces) {
var self = this;
_.each(pieces, function (piece) {
self.add(piece);
});
},

}

// ES6 the same inner function now can use its own “this”
{

addAll: function addAll(pieces) {
_.each(pieces, piece => this.add(piece));
},

}

4. Toán tử spread mới

Toán tử spread mới được đánh dấu bằng 3 dấu chấm (…), và chúng ta có thể sử dụng nó để đánh dấu nơi có nhiều mục được chờ đợi. Một trong những trường hợp sử dụng phổ biến nhất của toán tử spread là chèn các element của một array (mảng) vào một array khác:

let myArray = [1, 2, 3];

let newArray = […myArray, 4, 5, 6];

console.log(newArray);
// 1, 2, 3, 4, 5, 6

Chúng ta cũng thể sử dụng toán tử spread trong các lời gọi hàm (function call) mà chúng ta muốn được thông qua trong các argument (đối số) từ một array:

let myArray = [1, 2, 3];

function sum(a, b, c) {
return a + b + c;
}

console.log(sum(…myArray));
// 6

Toán tử spread thì khá linh hoạt, khi nó có thể được sử dụng nhiều lần trong cùng một array hay lời gọi hàm.

5. Các giá trị mặc định dành cho tham số & các rest parameter mới

Đối với ECMASScript 6, chúng ta có thêm các giá trị vào các parameter (tham số) của một hàm. Điều này có nghĩa là nếu chúng ta không được thông qua trong các đối số tiếp theo trong lời gọi hàm, thì các parameter mặc định sẽ được sử dụng. Trong ES5, các giá trị mặc định của các tham số thì luôn thiết lập là undefined, do đó trong ES6 chúng ta có thể thiết lập chúng thành bất cứ điều gì mà chúng ta muốn, đây rõ ràng là một cải tiến quan trọng của ngôn ngữ.

function sum(a = 2, b = 4) {
return a + b;
}

console.log( sum() );
// 6

console.log( sum(3, 6) );
// 9

ES6 cũng giới thiệu một loại tham số mới có tên gọi là rest parameters. Chúng hoạt động tương tự các toán tử spread. Chúng rất tiện ích nếu các lập trình viên không biết có bao nhiêu đối số sẽ được thông qua tiếp theo trong lời gọi hàm. Chúng ta có thể sử dụng các property và methods của đối tượng Array trên các rest parameter:

function putInAlphabet(…args) {

let sorted = args.sort();
return sorted;

}

console.log( putInAlphabet(“e”,”c”,”m”,”a”,”s”,”c”,”r”,”i”,”p”,”t”) );
// a,c,c,e,i,m,p,r,s,t

6. Câu lệnh for…of mới

Với sự hỗ trợ của vòng lặp mới for…of, chúng ta có thể lặp đi lặp lại các array hay các phần tử iterable một cách dễ dàng. Cùng với câu lệnh for…of mới, ECMAScript 6 cũng giới thiệu hai phần tử iterable mới là: Map dành cho key/values maps, và Set dành cho các tập hợp giá trị độc nhất bao gồm các giá trị gốc và các phần tử tham chiếu. Khi chúng ta sử dụng câu lệnh for…of, thì lập trình bên trong block được thực thi cho mỗi element của phần tử iterable.

let myArray = [1, 2, 3, 4, 5];
let sum = 0;

for (let i of myArray) {
sum += i;
}

console.log(sum);
// 15 (= 1 + 2 + 3 + 4 + 5)

7. Template Literals

ECMAScript 6 cung cấp cho chúng ta một giải pháp thay thế mới dành cho string concatenation. Template literals cho phép tạo ra dễ dàng các template mà chúng ta có thể đặt vào các giá trị khác nhau cho bất kỳ nơi nào chúng ta muốn. Để thực hiện như vậy chúng ta cần sử dụng cú pháp ${…} ở mọi nơi mà muốn chèn dữ liệu vào để chúng ta có thể được thông qua từ các biến, các array, hay các phần tử theo cách sau đây:

let customer = { title: ‘Ms’, firstname: ‘Jane’, surname: ‘Doe’, age: ’34’ };

let template = Dear ${customer.title} ${customer.firstname} ${customer.surname}!
Happy ${customer.age}th birthday!
;

console.log(template);
// Dear Ms Jane Doe! Happy 34th birthday!

8. Các class (lớp)

ES6 giới thiệu các lớp JavaScript được xây dựng dựa theo các kế thừa (inheritance) theo nguyên mẫu hiện có. Cú pháp mới tạo ra sự dễ hiểu hơn nhằm tạo ra các đối tượng, sử dụng sự kế thừa, và tái sử dụng lập trình. Và cũng mang đến sự dễ dàng dành cho các lập trình viên đến từ các ngôn ngữ khác để hiểu rõ cách JavaScript hoạt động.

Trong các lớp của ES6 được khai báo với từ khóa mới class, và cần phải có method constructor() – được gọi khi một đối tượng mới được tạo ra bằng cách sử dụng cú pháp new myClass(). Ngoài ra còn có thể mở rộng các lớp mới cùng với cú pháp class Child extends Parent mà chúng ta đã quen thuộc từ các ngon ngữ khác như PHP. Bạn cũng nên lưu ý rằng: không giống như khai báo biến và hàm, sự khai báo class thì KHÔNG có trong ECMAScript 6.

class Polygon {
constructor(height, width) { //class constructor
this.name = ‘Polygon’;
this.height = height;
this.width = width;
}

sayName() { //class method
console.log(‘Hi, I am a’, this.name + ‘.’);
}
}

let myPolygon = new Polygon(5, 6);

console.log(myPolygon.sayName());
// Hi, I am a Polygon.

9. Các mô đun

Bạn đã từng bao giờ tự hỏi liệu sẽ thế nào nếu JavaScript là modular không? Dĩ nhiên, sẽ có các giải pháp thay thế chẳng hạn như CommonJS (được sử dụng trong Node.js) hay AMD (Asynchronous Module Definition) (được sử dụng trong RequireJS), nhưng ES6 giới thiệu các module như là một tính năng riêng.

Chúng ta cần xác định mỗi module ở tệp tin riêng của nó, sau đó sử dụng từ khóa export để xuất các biến và các hàm cho các tệp tin khác, và từ khóa import để nhập chúng từ các tệp tin khác, theo cấu trúc sau đây:

// functions.js

function cube(a) {
return a * a * a;
}

function cubeRoot(a) {
return Math.cbrt(a);
}

export { cube, cubeRoot}
// or: export { cube as cb, cubeRoot as cr }

// app.js

import { cube, cubeRoot } from ‘functions’;

console.log(cube(4));
// 64

console.log(cubeRoot(125));
// 5

Giải pháp này rất thông minh, do code được lưu trữ trong một module mà không thể thấy từ bên ngoài, và chúng ta chỉ cần xuất phần mà chúng ta muốn sử dụng bởi các tệp tin khác. Chúng ta có thể thực hiện nhiều điều tuyệt vời khác với ES6 Modules, bạn có tìm thấy các module của ES6 khác tại đây.

10. Nhiều methods mới

ECMAScript 6 giới thiệu nhiều method mới cho String Prototype, Array Object, Array Prototype, và Math Object hiện có. Các method mới có thể cải thiện đáng kể cách chúng ta vận hành các đối tượng này. Mozilla Dev có các ví dụ lập trình hay về những sự bổ sung mới, điều này rất đáng để chúng ta bỏ ra thời gian tìm hiểu và thực nghiệm.

Chia sẻ bài viết ngay

Nguồn bài viết : http://www.hongkiat.com/