Những điều làm ES6 được yêu thích



  • ECMAScript (hay ES) là một chuẩn đặc tả ngôn ngữ kịch bản và nó được tạo ra để tiêu chuẩn hoá cho JavaScript. ECMAScript bản đầu tiên (ES1) ra đời năm 1997 và hiện nay đã trải qua rất nhiều phiên bản. Trong đó, phiên bản ES6 ra đời như một làn gió mới khiến người dùng JavaScript thích thú nhiều hơn.

    Bài viết hôm nay hãy cùng mình tìm hiểu những điều làm ES6 được yêu thích như thế nhé 😎

    Let’s get started !

    e8c4aeab-a019-464d-9b79-3b0c3ffe3afc-image.png

    Lịch sử phát triển của JavaScript / ECMAScript

    24cdbdff-3a6a-4e04-a399-1f136387b458-image.png

    d85f07ca-b2c9-4cec-9184-b3c721a67962-image.png
    Nguồn: JS / ECMA History – W3School

    Như bạn có thể thấy, ES6 (ECMA2015) ra đời năm 2015 và được hỗ trợ tất cả trình duyệt năm 2018. Nên bạn có thể thoải mái viết ES6 rồi nhé 😗 Hiện tại thì đã có phiên bản ES12, mình sẽ có bài viết nói về các tính năng mới của version này sau nhé.

    1. Constant

    Trong ES5 bạn không thể dùng từ khoá const để định nghĩa 1 biến bất biến (constant). Mà bạn có thể dùng Object.defineProperty để làm điều đó.

    // ES5
    Object.defineProperty (window, "VAR_CONSTANT",{ value : 10, writable: false });
    // ES6
    const VAR_CONSTANT = 10;
    

    2. Scoping without hoisting

    Trong ES5, bạn dùng từ khoá var để khai báo 1 biến nào đó. Điều này dẫn đến tình trạng hoisting.

    Hoisting là hiểu đơn giản là bạn có thể khai báo lại một biến khi nó đã được sử dụng (vì các biến sẽ được tự động chuyển lên đầu scope để khai báo). Điều này khiến việc quản lý biến của chúng ta trở nên rất phức tạp và dễ bị nhầm lẫn.

    Với ES6, bạn có thể giải quyết nó bằng cách khai báo từ khoá với let, const.

    // ES5
    console.log(a); // undefined
    var a = 5; // a = 5
    var a = 8; // a = 8
    // Tương đương (trình duyệt tự hiểu)
    var a;
    console.log(a);
    a = 5;
    
    // ES6
    console.log(a); // Error: a is not defined
    let a = 5; // a = 5
    let a = 6; // Error: Identifier 'a' has already been declared
    

    3. Arrow functions

    Trong ES6, bạn có một cách định nghĩa function kiểu khác bằng cách sử dụng ký tự =>. Với cách này code của bạn sẽ ngắn gọn và tường minh hơn nhiều.

    // ES5
    odds  = evens.map(function (v) { return v + 1; });
    pairs = evens.map(function (v) { return { even: v, odd: v + 1 }; });
    nums  = evens.map(function (v, i) { return v + i; });
    const doSomething = function(){
      // ...
    }
    // ES6
    odds  = evens.map(v => v + 1);
    pairs = evens.map(v => ({ even: v, odd: v + 1 }));
    nums  = evens.map((v, i) => v + i);
    const doSomething = () => {
      // ...
    }
    

    Ngoài ra, Arrow functions còn giải quyết vấn đề binding this. Bạn có thể tham khảo thêm ở đây nhé.

    4. Default Parameter Values

    Với ES6, bạn có thể gán các giá trị mặc định cho các tham số của hàm, trong trường hợp người dùng không truyền vào thì function sẽ tự lấy giá trị đó để làm mặc định.

    // ES5
    function f (x, y, z) {
        if (y === undefined)
            y = 7;
        if (z === undefined)
            z = 42;
        return x + y + z;
    };
    f(1) === 50; // true
    // ES6
    function f (x, y = 7, z = 42) {
        return x + y + z
    }
    f(1) === 50; // true
    

    5. Rest Parameter

    Trong ES6, bạn có thể tổng hợp các tham số còn lại mà người dùng truyền vào hàm thành một tham số duy nhất, một cách ngắn gọn hơn so với ES5 với rest parameter. Điều này rất hữu ích khi bạn không biết trước được chính xác số lượng tham số mà người dùng truyền vào.

    6. Toán tử Spread

    Toán tử … (spread) giúp bạn trải các phần tử của một tập hợp có thể lặp lại (như một mảng hoặc thậm chí một chuỗi) thành cả phần tử và các tham số hàm riêng lẻ. Mình hay dùng toán tử này để clone một mảng đơn giản.

    // ES5
    var params = [ "hello", true, 7 ];
    var other = [ 1, 2 ].concat(params); // [ 1, 2, "hello", true, 7 ]
    // ES56
    var params = [ "hello", true, 7 ];
    var other = [ 1, 2, ...params ]; // [ 1, 2, "hello", true, 7 ]
    

    7. Template Literals hay Template String

    ES6 hỗ trợ template string, giúp việc nối các chuỗi của chúng ta trở nên dễ dàng và tường minh hơn rất nhiều so với ES5.

    var age = 18;
    var firstName = "Dyno";
    var lastName = "Nguyen";
    // expect: Xin chào Dyno Nguyen 18 tuổi.
    // ES5
    var message = "Xin chào " + firstName + " " + lastName + " " + age.toString() + " tuổi.";
    // ES6
    var message = `Xin chào ${firstName} ${lastName} ${age} tuổi.`;
    

    Không những thế, với template string bạn có thể viết các chuỗi nhiều dòng liện tục mà không cần dùng các ký tự đặc biệt, hay phải cộng các chuỗi lại (multi-line string hay raw string).

    // ES5
    var message = "Xin chào!\n" + "Tôi là Dyno Nguyễn.\n" + "Năm nay tôi vừa tròn 18 tuổi.\n";
    // ES6
    var message = `Xin chào!
    Tôi là Dyno Nguyễn.
    Năm nay tôi vừa tròn 18 tuổi.`;
    

    8. Destructuring Assignment

    Đây là điều mình thích nhất trong ES6. Với Destructuring Assignment, mọi khai báo trở nên ngắn gọn hơn rất nhiều. Cùng mình tìm hiểu qua một vài ví dụ bên dưới nhé.

    // Rút ngắn khai báo với mảng
    // ES5
    var list = [ 1, 2, 3 ];
    var a = list[0], b = list[2]; // a = 1, b = 3;
    // ES6
    var list = [ 1, 2, 3 ]
    var [ a, , b ] = list; // a = 1, b = 3;
    
    // Swap a, b;
    // ES5
    var temp = a;
    a = b;
    b = temp;
    // ES6
    [a, b] = [b, a];
    
    function getObj(){
      return { a: 1, b: 2, c: 3 };
    }
    // ES5
    var obj = getObj();
    var a = obj.a;
    var b = obj.b;
    var newName = obj.c;
    // ES6
    var { a, b, c: newName } = getObj();
    
    // Gán và đặt giá trị mặc định
    // ES5
    var obj = { a: 1 };
    var list = [ 1 ];
    var a = obj.a;
    var b = obj.b === undefined ? 2 : obj.b;
    var x = list[0];
    var y = list[1] === undefined ? 2 : list[1];
    // ES6
    var obj = { a: 1 }
    var list = [ 1 ]
    var { a, b = 2 } = obj
    var [ x, y = 2 ] = list
    

    Còn nhiều thứ khác nữa, bạn có thể tham khảo thêm ở đây nhé: JavaScript tips and tricks

    9. Enhanced Object Properties

    Rút ngắn cú pháp khai báo object với ES6 như sau:

    // ES5
    var x = 0, y = 0;
    var obj = { x: x, y: y };
    // ES 6
    var x = 0, y = 0
    var obj = { x, y }
    

    10. Promise

    ES6 cung cấp cho chúng ta từ khoá Promise để xử lý các trường hợp asynchronous một cách thuận tiện hơn. Tránh trường hợp callback hell ở ES5. Bạn có thể đọc thêm Callback, Promise và Async/Await trong Javascript để hiểu hơn nhé.

    dec09b36-b73c-42dc-aae6-f8712e371a25-image.png

    // ES 5
    function msgAfterTimeout (msg, who, timeout, onDone) {
        setTimeout(function () {
            onDone(msg + " Hello " + who + "!");
        }, timeout);
    }
    msgAfterTimeout("", "Foo", 100, function (msg) {
        msgAfterTimeout(msg, "Bar", 200, function (msg) {
            console.log("done after 300ms:" + msg);
        });
    });
    // ES6
    function msgAfterTimeout (msg, who, timeout) {
        return new Promise((resolve, reject) => {
            setTimeout(() => resolve(`${msg} Hello ${who}!`), timeout)
        })
    }
    msgAfterTimeout("", "Foo", 100).then((msg) =>
        msgAfterTimeout(msg, "Bar", 200)
    ).then((msg) => {
        console.log(`done after 300ms:${msg}`)
    })
    

    11. Map và Set

    ES6 đã bổ sung thêm 2 cấu trúc dữ liệu là set và map, 2 dạng cấu trúc dữ liệu này tuy ít sử dụng nhưng vẫn rất hữu ích trong nhiều trường hợp. Mình sẽ có bài viết chi tiết nói về 2 cấu trúc này sau nhé 😙

    • Map là cấu trúc dữ liệu mà ta có thể lưu trữ dưới dạng key-value.
    • Set là một mảng chứa các dữ liệu không trùng lắp.
    const map = new Map();
    map.set('firstName', 'Dyno');
    map.set('lastName', 'Nguyen');
    map.get('firstName'); // Dyno
    
    const set = new Set();
    set.add(1);
    set.add(2);
    set.add(1);
    console.log(set); // Set(2){1, 2}
    

    12. Exporting & Importing Modules

    Ở ES6, nó cung cấp cho chúng ta từ khoá export và import để việc viết và nhập một module dễ dàng và trực quan hơn so với module.exports và require bên ES5. Ngoài ra, nhờ từ khoá import mà ta có rất nhiều cách để nhập một module vào linh hoạt hơn như import * as, import { … }, …

    // ES5
    var myModule = { x: 1, y: function(){ console.log('This is ES5') }}
    module.exports = myModule;
    var myModule = require('./myModule');
    // ES6
    const myModule = { x: 1, y: () => { console.log('This is ES5') }}
    export default myModule;
    import myModule from './myModule';
    

    13. For … of và For … in

    Trước đây, để duyệt qua các phần tử của mảng chúng ta hay dùng một biến index để duyệt từ 0 tới cuối mảng hoặc dùng forEach để tối ưu hơn trong vài trường hợp. Thì trong ES6 còn hỗ trợ chúng ta for … of để duyệt mảng khi chỉ cần lấy giá trị thay vì index.

    Và for … in để duyệt qua các key của một object.

    var nums = [1, 2, 3, 4, 5];
    // ES5
    var i, len = nums.length;
    for(i = 0; i < len; ++i){
      console.log(len[i]);
    }
    // ES6
    for(let num of nums){
      console.log(num);
    }
    

    14. Class và OOP trong JavaScript

    Từ ES6, Javascript đã hỗ trợ cho chúng ta class để viết OOP như các ngôn ngữ khác. Thay vì chỉ sử dụng object với prototype như ES5. Ngoài ra, nó còn hỗ trợ constructor, getter, setter, extends đầy đủ cho anh em nghịch ngợm 😂

    // ES5
    var Shape = function (id, x, y) {
        this.id = id;
        this.move(x, y);
    };
    Shape.prototype.move = function (x, y) {
        this.x = x;
        this.y = y;
    };
    // ES6
    class Shape {
        constructor (id, x, y) {
            this.id = id
            this.move(x, y)
        }
        move (x, y) {
            this.x = x
            this.y = y
        }
    }
    

    Tạm kết

    Tất cả bên trên là những điều làm ES6 được yêu thích theo ý kiến của mình. Ngoài ra thì vẫn còn một vài thứ hay ho khác, nhưng do bài viết này đã quá dài nên mình xin dừng tại đây. Các bạn có thể tham khảo thêm tại:

    Nguồn: https://dynonguyen.com/nhung-dieu-lam-es6-duoc-yeu-thich/


Log in to reply
 

});