0

Tìm hiểu về ECMAScript 6

Chào các bạn, mình đã trở lại và ăn hại hơn xưa =)) Trong bài viết này, mình xin giới thiệu về ECMAScript 6 (ES6). Một khái niệm mà Web Developer nào cũng nên biết!

I/ ECMAScript6 là gì ?

ECMAScript 6/ES6 là phiên bản mới nhất của bộ tiêu chuẩn ECMAScript – một bộ đặc tả tiêu chuẩn dành cho Javascript do Hiệp hội các nhà sản xuất máy tính Châu Âu (European Computer Manufacturers Association – ECMA) đề xuất. Phiên bảnECMAScript phổ biến ở thời điểm hiện tại (đầu 2015), và được hầu hết các trình duyệt hỗ trợ là ES5 và ES5.1 (ra mắt vào khoảng năm 2009 và 2011)

ES6 đã ra mắt vào giữa năm 2015 và được lấy tên chính thức là ES2015, với rất nhiều những tính năng mới lạ, và cần thiết đối với sự phát triển chóng mặt của Javascript trong những năm gần đây. Ngoài ra, phiên bản mới nhất của bộ đặc tả tiêu chuẩn này là ES7 cũng đang được phát triển, tuy chưa định ngày ra mắt chính thức nhưng cũng đã bắt đầu gây được sự chú ý của giới công nghệ với những tính năgn hấp dẫn như async function,observer,…

II/ Các tính năng mới trong ECMAScript6

  1. Arrow Functions
  • Arrow là một dạng viết tắt của các function, sử dụng dấu => thay vì phải viết function
  • Để các bạn dễ hiểu hơn thì mình xin giới thiệu 2 cách viết, 1 cách dùng ECMAScript 5 và một ví dụ dùng ECMAScript 6.

1.1/ Expression Bodies

Cú pháp trong ECMAScript 5

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; });

Cú pháp trong ECMAScript 6

odds  = evens.map(v => v + 1)
pairs = evens.map(v => ({ even: v, odd: v + 1 }))
nums  = evens.map((v, i) => v + i)

1.2/ Statement Bodies

Cú pháp trong ECMAScript 5

nums.forEach(function (v) {
   if (v % 5 === 0)
       fives.push(v);
});

Cú pháp trong ECMAScript 6

nums.forEach(v => {
   if (v % 5 === 0)
       fives.push(v)
})

1.3/ Lexical this

Cú pháp trong ECMAScript 5

this.nums.forEach((v) => {
    if (v % 5 === 0)
        this.fives.push(v)
})

Cú pháp trong ECMAScript 6

var self = this;
this.nums.forEach(function (v) {
    if (v % 5 === 0)
        self.fives.push(v);
});

==> Qua các ví dụ trên thì các bạn có thể thấy rằng trong ECMAScript 6 đã thay thế function bằng dấu => trong ECMAScript 6

2. Class

Trong javascript thông thường, để xây dựng và kế thừa các class, chúng ta phải thiết kế theo hướng sử dụng Prototype (prototype-based OO).

Hiểu được sự khó khăn này, ES6 đã giải quyết được vấn đề này bằng cách xây dựng bộ cú pháp đơn giản, dễ hơn rất nhiều so với sử dụng Prototype. Cú pháp gần giống với PHP, C++

Ngoài việc xây dựng class đơn giản thì ES6 còn hỗ trợ việc kế thừa, hỗ trợ các static method, constructor,...

2.1/ Định nghĩa một class

Cú pháp trong ECMAScript 5

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;
};

Cú pháp trong ECMAScript 6

class Shape {
    constructor (id, x, y) {
        this.id = id
        this.move(x, y)
    }
    move (x, y) {
        this.x = x
        this.y = y
    }
}

==> Qua 2 ví dụ về cách khai báo class trong ES5 và ES6 thì rõ ràng các bạn có thể thấy được sự khác biết rất lớn phải không nào

2.2/ Kế thừa

Cú pháp trong ECMAScript 5

var Rectangle = function (id, x, y, width, height) {
    Shape.call(this, id, x, y);
    this.width  = width;
    this.height = height;
};
Rectangle.prototype = Object.create(Shape.prototype);
Rectangle.prototype.constructor = Rectangle;
var Circle = function (id, x, y, radius) {
    Shape.call(this, id, x, y);
    this.radius = radius;
};
Circle.prototype = Object.create(Shape.prototype);
Circle.prototype.constructor = Circle;

Cú pháp trong ECMAScript 6

class Rectangle extends Shape {
    constructor (id, x, y, width, height) {
        super(id, x, y)
        this.width  = width
        this.height = height
    }
}
class Circle extends Shape {
    constructor (id, x, y, radius) {
        super(id, x, y)
        this.radius = radius
    }
}

==> Qua 2 ví dụ về cách extends class trong ES5 và ES6, chúng ta có thể thấy sự khác biệt rất lớn. Syntax sử dụng trong ES6 đơn giản, rất clear, và gần gần giống như các ngôn ngữ như java, php, c++,..

2.3/ Base Class Access

Cú pháp trong ECMAScript 5

var Shape = function (id, x, y) {};
Shape.prototype.toString = function (x, y) {
    return "Shape(" + this.id + ")"
};
var Rectangle = function (id, x, y, width, height) {
    Shape.call(this, id, x, y);};
Rectangle.prototype.toString = function () {
    return "Rectangle > " + Shape.prototype.toString.call(this);
};
var Circle = function (id, x, y, radius) {
    Shape.call(this, id, x, y);};
Circle.prototype.toString = function () {
    return "Circle > " + Shape.prototype.toString.call(this);
};

Cú pháp trong ECMAScript 6

class Shape {toString () {
        return `Shape(${this.id})`
    }
}
class Rectangle extends Shape {
    constructor (id, x, y, width, height) {
        super(id, x, y)}
    toString () {
        return "Rectangle > " + super.toString()
    }
}
class Circle extends Shape {
    constructor (id, x, y, radius) {
        super(id, x, y)}
    toString () {
        return "Circle > " + super.toString()
    }
}

2.4/ Static Members

Cú pháp trong ECMAScript 5

var Rectangle = function (id, x, y, width, height) {};
Rectangle.defaultRectangle = function () {
    return new Rectangle("default", 0, 0, 100, 100);
};
var Circle = function (id, x, y, width, height) {};
Circle.defaultCircle = function () {
    return new Circle("default", 0, 0, 100);
};
var defRectangle = Rectangle.defaultRectangle();
var defCircle    = Circle.defaultCircle();

Cú pháp trong ECMAScript 6

class Rectangle extends Shape {static defaultRectangle () {
        return new Rectangle("default", 0, 0, 100, 100)
    }
}
class Circle extends Shape {static defaultCircle () {
        return new Circle("default", 0, 0, 100)
    }
}
var defRectangle = Rectangle.defaultRectangle()
var defCircle    = Circle.defaultCircle()

2.5/ Getter/Setter

Cú pháp trong ECMAScript 5

var Rectangle = function (width, height) {
    this._width  = width;
    this._height = height;
};
Rectangle.prototype = {
    set width  (width)  { this._width = width;               },
    get width  ()       { return this._width;                },
    set height (height) { this._height = height;             },
    get height ()       { return this._height;               },
    get area   ()       { return this._width * this._height; }
};
var r = new Rectangle(50, 20);
r.area === 1000;

Cú pháp trong ECMAScript 6

class Rectangle {
    constructor (width, height) {
        this._width  = width
        this._height = height
    }
    set width  (width)  { this._width = width               }
    get width  ()       { return this._width                }
    set height (height) { this._height = height             }
    get height ()       { return this._height               }
    get area   ()       { return this._width * this._height }
}
var r = new Rectangle(50, 20)
r.area === 1000

3. Template Literals

Với ES6, việc xử lý chuỗi trong javascript trở nên cực kì đơn giản hơn bao giờ hết. Đặc biệt là nó hỗ trợ chuỗi nhiều dòng, đây là một điểm hản là nhiều bạn dev rất thích thú phải không nào 😄. Để hiểu hơn thì chúng ta đến với ví dụ sau nhé:

Cú pháp trong ECMAScript 5

var customer = { name: "Foo" };
var card = { amount: 7, product: "Bar", unitprice: 42 };
var message = "Hello " + customer.name + ",\n" +
"want to buy " + card.amount + " " + card.product + " for\n" +
"a total of " + (card.amount * card.unitprice) + " bucks?";

Cú pháp trong ECMAScript 6

var customer = { name: "Foo" }
var card = { amount: 7, product: "Bar", unitprice: 42 }
var message = `Hello ${customer.name},
want to buy ${card.amount} ${card.product} for
a total of ${card.amount * card.unitprice} bucks?`

==> Ở ES5 nếu các bạn muốn nối chuỗi trong cùng một hàng thì phải dùng dấu + để nối chuỗi giống như ví dụ trên

Còn trong ES6 thì các bạn chỉ dùng cặp dấu ``, nếu có expression trong chuỗi thì các bạn chỉ cần dùng dấu $ đứng trước cặp dấu ngoặc nhọn ({{ }}) như ví vụ trên.

4.Parameter handling

4.1 Giá trị mặc định cho tham số

Không biết các bạn có để ý đến điều này không, có một điểm là trong javascript thông thường thì các bạn không thế truyền giá trị mặc định cho tham số ở function. Hiểu được hạn chế này, ES6 đã support cho chúng ta phần này rất tốt. Nếu chưa hiểu thì các bạn có thể xem ví dụ dưới đây nhé:

Cú pháp trong ECMAScript 5

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

Cú pháp trong ECMAScript 6

function f (x, y = 7, z = 42) {
    return x + y + z
}
f(1) === 50

=> Qua 2 cách biểu diễn function ở trên thì các bạn có thể thấy rõ sự khác biêt đúng không nào. Trong ES5 thì các bạn không thế truyền giá trị mặc định cho tham số, ví dụ là tham số y, chúng ta phải kiểm tra trong phần thân của function. Rõ ràng điều này rất không hay.

Chính vì vậy trong ES6 thì các bạn có thể gán trực tiếp giá trị default cho tham số y luôn

4.2 Truyền tham số không xác định số lượng

Nghe qua thì có vẻ khó hiểu đúng không nào, thôi xem ví dụ trước đã để các bạn hiểu phần nào rồi mình sẽ giải thích thêm:

Cú pháp trong ECMAScript 5

function f (x, y) {
    var a = Array.prototype.slice.call(arguments, 2);
    return (x + y) * a.length;
};
f(1, 2, "hello", true, 7) === 9;

Cú pháp trong ECMAScript 6

function f (x, y, ...a) {
    return (x + y) * a.length
}
f(1, 2, "hello", true, 7) === 9

Nhìn qua đoạn code ở phần ES5 chắc hẳn các bạn đã hiểu được ý nghĩa đúng không nào? Còn ở ES6 thì sao! Trong function f ở đối số thứ 3 (...a). Ở đây đối số này được hiểu là một array.Thay vì bạn phải sử dụng 1 biến là array thì các bạn có thể dùng cách này để biểu diễn array

Trong nội dung bài viết này thì mình chỉ giới thiệu đến đây. Còn một số phần quan trọng khác như: Module, module loader, Map, Set, WeakMap, WeakSet, Promises,... thì mình sẽ giới thiệu trong bài viết tiếp theo

Xin chào và hẹn các bạn trong bài viết tiếp theo nhé !


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí