ES6 Arrow Functions

Mở đầu

Trong ES6, arrow functions là một cú pháp mới dùng để viết các hàm trong JavaScript. Nó giúp tiết kiệm thời gian phát triển và đơn giản hóa phạm vi function (function scope). Trong bài viết này, mình sẽ giới thiệu chi tiết về arrow function, cách sử dụng chúng, các cú pháp phổ biến, trường hợp sử dụng phổ biến, cũng như ưu/nhược điểm của việc sử dụng chúng.

Arrow function là gì

Arrow function - còn được gọi là "fat arrow", là cú pháp được mượn từ CoffeeScript (một ngôn ngữ chuyển tiếp), cú pháp này là cách ngắn gọn hơn dùng để viết function. Ở đây sử dụng kí tự =>, trông giống như một mũi tên "béo". Arrow function là một hàm vô danh và nó thay đổi cách this bind đến function. Arrow function làm code của ta trông ngắn gọn hơn, giúp đơn giản hóa function scoping cũng như từ khóa this. Arrow function hoạt động tương tự như Lambdas trong các ngôn ngữ khác như C # hay Python. Bằng cách sử dụng arrow function, chúng ta tránh được việc phải gõ từ khoá function, return và dấu ngoặc nhọn.

Cách dùng arrow function

Có khá nhiều cú pháp có thể dùng với arrow function. EcmaScript.org, MDN có liệt kê một danh sách đầy đủ các cú pháp có thể được dùng. Ở đây tôi sẽ đề cập đến những cú pháp phổ biến nhất.

Trong trường hợp nhiều tham số

// (param1, param2, paramN) => expression 
 
// ES5 
var multiply = function(x, y) {
    return x * y;
}; 
 
// ES6 
var multiply = (x, y) => { return x * y };

Ví dụ trên cho cùng một kết quả, tuy nhiên cú pháp với arrow function tốn ít dòng mã hơn. Trong trường hợp chỉ có một biểu thức thì không cần tới dấu ngoặc nhọn: Ví dụ trên có thể viết lại như sau:

var multiply = (x, y) => x * y ;

Trong trường hợp 1 tham số

Dấu ngoặc đơn là optional khi chỉ có một tham số

//ES5 
var phraseSplitterEs5 = function phraseSplitter(phrase) { 
    return phrase.split(' '); 
}; 
 
//ES6 
var phraseSplitterEs6 = phrase => phrase.split(" "); 
 
console.log(phraseSplitterEs6("ES6 Awesomeness"));  // ["ES6", "Awesomeness"]

Trong trường hợp không có tham số

Dấu ngoặc đơn là bắt buộc khi không có tham số.

//ES5 
var docLogEs5 = function docLog() { 
    console.log(document); 
}; 
 
//ES6 
var docLogEs6 = () => { console.log(document); } 
docLogEs6(); // #document... <html> ….

Cú pháp với Object literal

Arrow function cũng tương tự như biểu thức function, có thể được sử dụng để trả về một object literal. Phần body của function cần được bao bọc trong ngoặc tròn, để phân biệt giữa object và function block (cả hai đều sử dụng dấu ngoặc nhọn).

//ES5 
var setNameIdsEs5 = function setNameIds(id, name) { 
    return { 
        id: id, 
        name: name 
    }; 
}; 
 
// ES6 
var setNameIdsEs6 = (id, name) => ({ id: id, name: name }); 
 
(setNameIdsEs6 (4, "Kyle"));   // Object {id: 4, name: "Kyle"} 

Khi nào thì nên sử dụng arrow function

Một usecase phổ biến áp dung arrow function là thao tác mảng, thông thường là khi dùng map hoặc reduce. Có 1 mảng như sau:

var smartPhones = [ 
    { name: 'iphone', price: 649 }, 
    { name: 'Galaxy S6', price: 576 }, 
    { name: 'Galaxy Note 5', price: 489 } 
];

Để lấy 1 mảng toàn tên các smart phones, ta thực hiện:

// ES5 
console.log(smartPhones.map(function(smartPhone){
    return smartPhone.price;
}); // [649, 576, 489]

Với arrow function, có thể viết rút gọn lại thành

// ES6 
console.log(smartPhones.map(smartPhone => smartPhone.price)); // [649, 576, 489]

Promises và Callbacks

Code mà sử dụng các callback asynchronous hay promise thường chứa nhiều từ khóa functionreturn do chaining nhiều lần:

// ES5
aAsync().then(function() {
    returnbAsync();
}).then(function() {
    returncAsync();
}).done(function() {
    finish();
});

Sử dụng arrow function:

// ES6
aAsync().then(() => bAsync()).then(() => cAsync()).done(() => finish);

Lưu ý trong việc sử dụng arrow function

Cú pháp arrrow function là chức năng khá hữu ích trong ECMAScript, tuy nhiên ngoài những ưu điểm thì nó cũng có những hạn chế như việc nó khiến code của bạn tuy ngắn nhưng lại khó hiểu. Dưới đây là những lưu ý

this

từ khóa this hoạt động khác hoàn toàn trong arrow function. Các phương thức call (), apply (), và bind () sẽ không thay đổi giá trị của this trong arrow function. (Trong thực tế, giá trị của this bên trong một hàm đơn giản là không thể thay đổi - nó sẽ luôn là giá trị tương tự như khi hàm được gọi) Nếu bạn cần bind đến một giá trị khác, cần sử dụng function expression như bình thường.

Constructors

Arrow function không thể được sử dụng làm constructor như function. Nếu khởi tạo new với arrow function, nó sẽ throw ra lỗi. Arrow function không có thuộc tính prototype hay internal methods. Trong trường hợp đó nên dùng cú pháp tạo class của ES6.

Generators

Arrow function được thiết kế không thể sử dụng như là generator. Thay vào đó ta có thể sử dụng từ khóa generators trong ES6.

Tốt nhất nên cân đối giữa việc dùng function và dùng arrow function như sau:

  • Sử dụng function trong global scope trong Object.prototype properties
  • Sử dụng class cho object constructors.
  • Sử dụng => ở những chố còn lại

Nguồn tham khảo

  1. Sitepoint