Xem Nhiều 3/2023 #️ 10 Tính Năng Của Es6 (Ecmascript2015) Mọi Lập Trình Javascript Phải Biết # Top 4 Trend | Tvzoneplus.com

Xem Nhiều 3/2023 # 10 Tính Năng Của Es6 (Ecmascript2015) Mọi Lập Trình Javascript Phải Biết # Top 4 Trend

Cập nhật thông tin chi tiết về 10 Tính Năng Của Es6 (Ecmascript2015) Mọi Lập Trình Javascript Phải Biết mới nhất trên website Tvzoneplus.com. Hy vọng nội dung bài viết sẽ đáp ứng được nhu cầu của bạn, chúng tôi sẽ thường xuyên cập nhật mới nội dung để bạn nhận được thông tin nhanh chóng và chính xác nhất.

Bài viết được dịch từ: webapplog.com

Bài viết này sẽ giới thiệu nhanh cho bạn về ES6. Nếu bạn chưa biết ES6 là gì, thì nó là một phiên bản mới của Javascript. Nếu bạn là một kỹ sư phần mềm bận rộn (có ai lại không nhỉ?), hãy dành thời gian để học 10 tính năng tốt nhất thế hệ tiếp theo của ngôn ngữ lập trình phổ biến nhất – JavaScript.

Đây là danh sách 10 tính năng tốt nhất của ES6 cho những kỹ sư phần mềm bận rộn (sắp xếp ngẫu nhiên):

Default Parameters in ES6

Template Literals in ES6

Multi-line String in ES6

Destructuring Assignment in ES6

Enhanced Object Literals in ES6

Arrow Function in ES6

Promises in ES6

Block-Scoped Constructs Let and Cont

Classes in ES6

Modules in ES6

Chú ý: Danh sách này mang tính chủ quan. Nó không nhằm mục đích phủ nhận sự hữu dụng của các tính năng khác trong ES6, cái không xuất hiện trong danh sách lý do đơn giản là tôi giới hạn trong 10 tính năng.

Đầu tiên, là một chút về lịch sử của JavaScript dành cho những ai chưa biết:

1995: JavaScript được ra đời với tên gọi LiveScript

1997: Chuẩn ECMAScript được thành lập

1999: ES3 ra đời và IE5 là tất cả cơn thịnh nộ

2000 – 2005: XMLHttpRequest cũng được biết đến như AJAX, làm tăng sự phổ biến của các ứng dụng như Outlook Web Access (2000) và Oddpost (2002), Gmail (2004), và Google Maps (2005).

2009: ES5 ra đời (đây là cái được sử dụng phổ biến nhất hiện nay) với forEach, Object.keys, Object.create (Douglas Crockford), và chuẩn JSON.

2015: ES6/ECMAScript2015 ra đời, nó có hầu hết syntatic sugar.

Vậy là đủ về lịch sử, tiếp theo hãy xem xét code

1. Default Parameters in ES6

Chúng ta có các câu lệnh để định nghĩa các tham số mặc định:

Mọi thứ vẫn ổn cho đến khi giá trị là 0 và bởi vì trong JavaScript 0 là falsy nên nó sẽ mặc định là giá trị mà chúng ta hard-coded (50, 'red', 'http://azat.co'), vì thế chúng ta cần sử dụng cách khác. Trong ES6, chúng ta có thể đặt các giá trị mặc định khi khai báo tham số như thế này:

var link = function(height = 50, color = 'red', url = 'http://azat.co') { ... }

Cú pháp này tương tự Ruby!

2. Template Literals in ES6

Template Literals hay interpolation trong các ngôn ngữ khác là một cách hiển thị các biến trong chuỗi. Trong ES5 chúng ta làm như thế này:

var name = 'Your name is ' + first + ' ' + last + '.' var url = 'http://localhost:3000/api/messages/' + id

May mắn, trong ES6 chúng ta có thể sử dụng cú pháp mới ${NAME} bên trong chuỗi:

var name = `Your name is ${first} ${last}.` var url = `http://localhost:3000/api/messages/${id}`

3. Multi-line String in ES6

Một syntactic sugar khác là chuỗi có nhiều dòng (multi-line string). Trong ES5, chúng ta làm như thế này:

var roadPoem = 'Then took the other, as just as fair,nt' + 'And having perhaps the better claimnt' + 'Because it was grassy and wanted wear,nt' + 'Though as for that the passing therent' + 'Had worn them really about the same,nt' var fourAgreements = 'You have the right to be you.n You can only be you when you do your best.'

Trong ES6, chỉ cần sử dụng dấu backticks:

var roadPoem = `Then took the other, as just as fair, And having perhaps the better claim Because it was grassy and wanted wear, Though as for that the passing there Had worn them really about the same,` var fourAgreements = `You have the right to be you. You can only be you when you do your best.`

4. Destructuring Assignment in ES6

Destructuring có thể là một khái niệm khó hiểu, hãy xem phép gán đơn giản này nơi các khóa house và mouse là các biến house và mouse:

var data = $('body').data(),

Một ví dụ khác của phép gán destructuring (từ Node.js):

var jsonMiddleware = require('body-parser').json var body = req.body,

Trong ES6, chúng ta có thể thay thế code ES5 với các câu lệnh:

var {house, mouse} = $('body').data()

Điều này cũng làm việc với mảng:

var [col1, col2] = $('.column'), [line1, line2, line3, , line5] = file.split('n')

Có lẽ phải mất một khoảng thời gian để sử dụng cú pháp gán destructuring, nhưng nó rất hữu ích.

5. Enhanced Object Literals in ES6

Cái bạn có thể làm với object literals giờ đang thay đổi! Chúng ta đi từ phiên bản của JSON trong ES5 tới một thứ gần giống class trong ES6.

Đây là một đối tượng điển hình trong ES5 với một vài phương thức và thuộc tính:

var serviceBase = {port: 3000, url: 'azat.co'}, getAccounts = function(){return [1,2,3]} var accountServiceES5 = { port: serviceBase.port, url: chúng tôi getAccounts: getAccounts, toString: function() { return JSON.stringify(this.valueOf()) }, getUrl: function() {return "http://" + chúng tôi + ':' + this.port}, valueOf_1_2_3: getAccounts() }

Nếu muốn đẹp, chúng ta có thể kế thừa từ đối tượng seviceBase bằng cách tạo protoype với phương thức Object.create:

var accountServiceES5ObjectCreate = Object.create(serviceBase) var accountServiceES5ObjectCreate = { getAccounts: getAccounts, toString: function() { return JSON.stringify(this.valueOf()) }, getUrl: function() {return "http://" + chúng tôi + ':' + this.port}, valueOf_1_2_3: getAccounts() }

Nhưng vì lợi ích của ví dụ, chúng ta sẽ coi chúng tương tự. Trong ES6 object literal, phép gán getAccounts: getAccounts, trở thành chỉ getAccounts. Chúng ta thiết lập protoype ngay trong thuộc tính __proto__:

var serviceBase = {port: 3000, url: 'azat.co'}, getAccounts = function(){return [1,2,3]} var accountService = { __proto__: serviceBase, getAccounts,

Vì thế chúng ta có thể gọi super và các khóa động (valueOf_1_2_3):

toString() { return JSON.stringify((super.valueOf())) }, getUrl() {return "http://" + chúng tôi + ':' + this.port}, [ 'valueOf_' + getAccounts().join('_') ]: getAccounts() }; console.log(accountService)

Đây là sự cải tiến tuyệt vời cho object literals cũ!

6. Arrow Functions in ES6

Đây là tính năng mà tôi mong chờ nhất. Tôi thích CoffeeScript vì fat arrows. Hiện nay chúng có trong ES6. Fat arrow tuyệt vời bởi vì chúng tạo ra hành vi của thuộc tính í dụ this sẽ có cùng giá trị với bối cảnh (context) của hàm – nó không bị thay đổi. Thay đổi thường xảy ra mỗi lần bạn tạo một closure.

Sử dụng arrow function trong ES6 cho phép chúng ta không cần sử dụng that = this hoặc self = this hoặc _this = this hoặc .bind(this). Ví dụ đây là một đoạn code trong ES5:

Đây là code trong ES6 không có _this = this:

Đây là một ví dụ khác về cách chúng ta sử dụng call để truyền bối cảnh (context) tới hàm logUpperCase() trong ES5:

var logUpperCase = function() { var _this = this this.string = this.string.toUpperCase() return function () { return console.log(_this.string) } } logUpperCase.call({ string: 'es6 rocks' })()

Trong ES6, chúng ta không cần sử dụng _this

Đây là đoạn code tạo một mảng messages từ mảng ids:

var ids = ['5632953c4e345e145fdf2df8','563295464e345e145fdf2df9'] var messages = ids.map(function (value) { return "ID is " + value

Trong ES6 sẽ trở thành:

Bạn có thấy rằng tôi sử dụng string template? Một tính năng khác từ CoffeeScript... tôi thích chúng!

Cặp ngoặc đơn () không bắt buộc cho một tham số trong arrow function. Bạn cần chúng khi sử dụng nhiều hơn một tham số.

Trong ES5 hàm có một câu lệnh return rõ ràng:

var ids = ['5632953c4e345e145fdf2df8', '563295464e345e145fdf2df9']; var messages = ids.map(function (value, index, list) { return 'ID of ' + index + ' element is ' + value + ' '

Còn đây là phiên bản ES6 với cặp ngoặc đơn bao quanh các tham số và câu lệnh return không rõ ràng:

7. Promises trong ES6

Hãy xem xét một ví dụ bất đồng bộ với setTimeout():

setTimeout(function(){ console.log('Yay!') }, 1000)

Chúng ta có thể viết lại code trong ES6 với Promise:

var wait1000 = new Promise(function(resolve, reject) { setTimeout(resolve, 1000) }).then(function() { console.log('Yay!') })

Hoặc với arrow function:

Bạn có thể thấy số dòng code tăng từ 3 lên 5 mà không rõ lợi ích của Promise. Đúng vậy. Lợi ích sẽ rõ ràng nếu có nhiều khối lệnh logic lồng trong hàm setTimeout():

setTimeout(function(){ console.log('Yay!') setTimeout(function(){ console.log('Wheeyee!') }, 1000) }, 1000)

Đoạn code trên có thể viết lại trong ES6 với promise:

Bạn vẫn chưa bị thuyết phục rằng Promises tốt hơn các hàm callback thông thường? Tôi cũng vậy. Tôi nghĩ rằng một khi bạn có ý tưởng sử dụng callback và suy nghĩ cẩn thận về chúng thì không cần thêm sự phức tạp của promise.

8. Block-Scoped Constructs Let and Const

Let cho phép chúng ta khai báo biến trong phạm vi các khối lệnh. Các khối lệnh được định nghĩa bởi cặp ngoặc nhọn {}. Trong ES5, các khối không giới hạn phạm vi của các biến:

function calculateTotalAmount (vip) { var amount = 0 if (vip) { var amount = 1 } {

Kết quả của đoạn code trên là 1000. Wow! Đó thực sự là bug. Trong ES6, chúng sử dụng let để giới hạn phạm của biến trong các khối lệnh.

function calculateTotalAmount (vip) { var amount = 0

Kết quả của đoạn code trên là 0, bởi vì khối lệnh if sử dụng let. Nếu nó không có từ khóa let (amount = 1) kết quả sẽ là 1.

Khi ES6 giới thiệu từ khóa const, mọi thứ trở lên dễ dàng hơn, nó chỉ là một biến không thay đổi, và cũng giới hạn phạm vi trong các khối lệnh giống như let. Ví dụ, đoạn code bên dưới gồm nhiều hằng số trong các khối lệnh khác nhau:

function calculateTotalAmount (vip) { const amount = 0 if (vip) { const amount = 1 } {

Theo ý kiến của cá nhân tôi, let và const làm cho ngôn ngữ trở lên phức tạp hơn. Không có chúng, chúng ta chỉ có một hành vi, giờ chúng ta phải xem xét nhiều kịch bản hơn.

9. Classes trong ES6

Tạo và sử dụng class trong ES5 khá đau khổ, bởi vì không có từ khóa class. Ngoài ra, nhiều mẫu (pattern) kế thừa giống như pseudo classical, classical, functional chỉ làm tăng sự nhầm lẫn, giống như thêm dầu vào lửa trong cuộc chiến giữa các quan điểm lập trình JavaScript khác nhau.

Tôi sẽ không cho bạn thấy cách viết một class trong ES5, bởi vì có quá nhiều thứ. Hãy xem một ví dụ về class trong ES6 ngay. Tôi có thể nói với bạn rằng class của ES6 sử dụng prototype, không phải hướng tiếp cận funtion factory. Chúng ta có một class baseModel cái định nghĩa một hàm khởi tạo (constructor) và một phương thức getName():

class baseModel { constructor(options = {}, data = []) { class AccountModel extends baseModel { constructor(options, data) {

Để gọi hàm khởi tạo cha, sử dụng super() với các tham số:

super({private: true}, ['32113123123', '524214691'])

Nếu bạn muốn đẹp, bạn có thể thiết lập getter giống như thế này và accountsData sẽ có một thuộc tính:

get accountsData() {

Vậy làm thế nào để sử dụng câu thần chú này? Nó dễ như lừa một đứa trẻ 3 tuổi nghĩ rằng ông già Noel là có thật:

let accounts = new AccountModel(5) accounts.getName() console.log('Data is %s', accounts.accountsData)

Kết quả sẽ là:

Class name: Account Model Data is %s 32113123123,524214691

10. Modules in ES6

Trước ES6 JavaScript không hỗ trợ module. Mọi người thường sử dụng AMD, RequireJS, CommonJS và nhiều cái khác. Bây giờ trong ES6 bạn có thể sử dụng các import và export.

module.exports = { port: 3000, getAccounts: function() { ... } } var service = require('module.js') console.log(service.port) export var port = 3000 export function getAccounts(url) { ... }

Trong file main.js ES6, chúng ta sử dụng import {name} từ cú pháp 'my-module'. Ví dụ:

import {port, getAccounts} from 'module' console.log(port)

Chúng ta có thể import mọi thứ vào một biến service trong chúng tôi :

import * as service from 'module' console.log(service.port)

Cá nhân tôi thấy module trong ES6 lộn xộn. Vâng chúng trông hoành tráng hơn, nhưng chúng tôi module không thay đổi nhanh chóng. Nó tốt hơn vì chỉ có duy nhất một style JavaScript cho cả trình duyệt và server, vì thế tôi vẫn sử dụng CommonJS/Node.js.

Hỗ trợ cho module ES6 trong các trình duyệt chưa thể có ngay (tại thời điểm đang viết bài này - cuối năm 2015), vì thế bạn sẽ cần sử dụng một vài thứ chẳng hạn jspm để sử dụng module ES6.

Để biết thêm thông tin và ví dụ về module ES6, bạn có thể đọc ở đây.

Làm thế nào để sử dụng ES6 ngay hôm nay (Babel)

Đây là một ví dụ Gulp, đầu tiên là cài đặt plugin:

$ npm install --save-dev gulp-babel

Trong chúng tôi , định nghĩa một task build đọc file src/app.js và biên dịch tới thư mục build:

var gulp = require('gulp'), babel = require('gulp-babel') gulp.task('build', function () { return gulp.src('src/app.js') .pipe(babel()) .pipe(gulp.dest('build')) })

Node.js và ES6

Với chúng tôi bạn có thể biên dịch các file chúng tôi của mình với công cụ hoặc sử dụng module Babel độc lập là babel-core. Để cài đặt:

$ npm install --save-dev babel-core

Sau đó, trong chúng tôi bạn gọi hàm này:

require("babel-core").transform(es5Code, options)

Tóm tắt những tính năng của ES6

Còn nhiều tính năng đáng chú ý của ES6, cái mà bạn có thể không sử dụng (ít nhất là lúc này). Đây là danh sách các tính năng này:

New Math, Number, String, Array and Object methods

Binary and octal number types

Default rest spread

For of comprehensions

Symblols

Tail calls

Generators

New data structures like Map and Set

https://github.com/azat-co/cheatsheets/tree/master/es6

https://leanpub.com/understandinges6

https://leanpub.com/exploring-es6

Tổng Hợp Những Tính Năng Es6 Nổi Bật

Hàm mũi tên (arrow functions)

Chuỗi bản mẫu (template strings)

Object chân phương (object literals)

Phân rã biến (destructuring)

Rest và Spread

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

Lớp (class)

Promise

var foo = 1 function printFoo(shouldDo) { if (shouldDo) { var foo = 2 } return foo } console.log(printFoo(false)) console.log(printFoo(true))

Biến được khai báo với var sẽ có tầm vực bên trong hàm gần nhất (function scope), và sẽ được đẩy lên đầu của tầm vực (hoisting). Đó là lý do tại sao foo lại có giá trị undefined trong dòng console.log đầu tiên.

ES6 giới thiệu let và const như hai cách khai báo biến mới, hỗ trợ tầm vực theo khối (block scope) và không thực hiện hoisting.

let foo = 1 function printFoo(shouldDo) { if (shouldDo) { let foo = 2 console.log('Value of foo in scope', foo) } console.log('foo is out of block scope', foo) return foo } console.log(printFoo(false)) console.log(printFoo(true))

Điểm khác biệt giữa let và const là với const, bạn không thể gán giá trị mới cho biến sau khi khai báo, trong khi điều này lại có thể với let.

let foo = 2 foo = 3 console.log(foo) const baz = 2 baz = 3

const mang ý nghĩa “constant” chứ không phải “immutability”. Nghĩa là với các biến là object hay array, bạn vẫn có thể thay đổi giá trị bên trong của chúng.

const obj = { foo: 2 } obj.foo = 5 obj.bar = 3 console.log(obj) const arr = [1] arr.push(2) console.log(arr) obj = { baz: 4 } arr = []

Tính tương thích: Được hỗ trợ trên tất cả trình duyệt, kể cả IE11. Lời khuyên: Dùng const cho tất cả khai báo biến vì nó sẽ giúp bạn hạn chế trường hợp “vô tình” thay đổi giá trị của biến. Chỉ dùng let trong trường hợp bất khả kháng, và tránh xa var.

2. Hàm mũi tên

Hàm mũi tên — (fat) arrow functions — là một kiểu cú pháp rút gọn cho khai báo hàm trong JavaScript. Trước ES6, bạn khai báo một hàm trong JavaScript với từ khóa function.

function add(x, y) { return x + y } var add = function(x, y) { return x + y }

“Syntactic sugar” là cú pháp làm cho ngôn ngữ trở nên dễ đọc và dễ hiểu hơn, theo kiểu nó làm cho ngôn ngữ “ngọt ngào hơn” (sweeter) với lập trình viên.

Với hàm mũi tên trong ES6, bạn có thể viết lại thành:

return x + y }

Hàm mũi tên cũng hữu dụng để giải quyết vấn đề muôn thuở trong JavaScript: “which this is this?” — khái niệm con trỏ this. Với ES5, bạn hay gặp trường hợp giống như thế này:

'use strict' function App() { this.count = 0 setInterval(function() { console.log(this.count++) }, 1000) } var a = new App()

Trước ES6, mỗi khai báo hàm đều có một giá trị this tách biệt. Điều này làm cho đoạn code ở trên không hoạt động, vì this.count bên trong hàm của setInterval mang giá trị undefined. Cách giải quyết thông thường là đặt một biến self, that hay _this để giữ reference, hoặc sử dụng Function.prototype.bind.

function App() { this.count = 0 var self = this setInterval(function() { console.log(self.count++) }, 1000) } function App() { this.count = 0 function counter() { console.log(this.count++) } setInterval(counter.bind(this), 1000) }

Với hàm mũi tên trong ES6, giá trị của this chính là this trong tầm vực gần nhất với nó (lexical this). Do đó chúng ta không cần phải khai báo biến tạm hay dùng .bind nữa.

function App() { this.count = 0 }

Hàm mũi tên cũng rất hữu ích khi thao tác trên mảng và tiến hành chuyển đổi dữ liệu, giúp mã nguồn dễ đọc và rõ ràng hơn.

Tính tương thích: Trừ IE11, tất cả các trình duyệt còn lại đều hỗ trợ. Lời khuyên: Nếu có dùng đến this thì hàm mũi tên rất hữu dụng. Trường hợp không dùng thì…cũng hữu dụng luôn vì mã nguồn gọn gàng dễ đọc hơn. Với những trường hợp bạn muốn bao đóng giá trị của this chỉ gói gọn trong hàm của nó, dùng function.

3. Chuỗi bản mẫu

Chuỗi bản mẫu (template strings) là chuỗi chân phương (string literals) nhưng cho phép đính kèm biểu thức. Nó cũng cho phép khai báo chuỗi trên nhiều dòng. Để sử dụng, bạn dùng ký tự backtick ` (dấu huyền). Ví dụ như là:

const name = 'John' const greetings = `Hello ${name}, The result of 1 + 1 is ${1 + 1}, and the time is now ${Date.now()}.`

Vì chuỗi bản mẫu cũng chỉ là chuỗi nên bạn có thể gọi đến những phương thức của String.prototype.

;`Hello World`.substr(0, 5).toUpperCase()

Tính tương thích: Trừ IE11, tất cả các trình duyệt còn lại đều hỗ trợ. Lời khuyên: Dùng chuỗi bản mẫu khi bạn cần gắn biểu thức hay chuỗi có nội dung ở nhiều dòng. Còn lại thì vẫn dùng chuỗi bình thường với ' hay ".

4. Object chân phương (object literals)

Object chân phương (object literals) chỉ đơn giản là khai báo một object trong JavaScript như bạn đã làm bao năm nay.

var birthYear = 2000 var obj = { name: 'John', birthYear: birthYear, getAge: function(currentYear) { return currentYear - obj.birthYear } }

ES6 nâng cấp object chân phương, cho phép bạn khai báo tắt thuộc tính của object với biến cùng tên, và khai báo phương thức cho object.

const birthYear = 2000 const obj = { name: 'John', birthYear, getAge(currentYear) { return currentYear - this.birthYear } }

Một lưu ý với this là khi bạn dùng hàm mũi tên, this sẽ được lấy từ this trong tầm vực gần với nó nhất, chứ không trỏ đến đối tượng hiện tại. Do đó…

{ }

…sẽ không chạy như mong muốn, vì có thể this.birthYear mang giá trị undefined. Để sử dụng hàm mũi tên bạn phải viết lại như trước ES6.

{ }

Ngoài ra từ ES6 bạn cũng có thể khai báo thuộc tính cho object một cách linh động bằng cách sử dụng cú pháp [].

const attr = 'foo' const year = 2017 const obj = { [attr]: 1, ['now' + year]: 'wow' } console.log(obj)

Tính tương thích: Được hỗ trợ bởi tất cả trình duyệt const user = { name: 'John', age: 21 } const { name } = user console.log(name)

const arr = [1, 2, 3] const [first, second] = arr console.log(first, second)

const str = 'Hello' const [first, second] = str console.log(first, second)

Bạn cũng có thể phân rã các thuộc tính lồng nhau.

const userList = [ { name: 'John', age: 21, products: [{ name: 'Creamy Crustacean Omelette', price: 1200 }, { name: 'Galdin Gratin', price: 2300 }] } ] const [{ products: [{ price }] }] = userList console.log(price)

Với mảng hay chuỗi, bạn có thể bỏ qua phần tử không mong muốn khi phân rã.

const arr = [1, 2, 3] const [first, , third] = arr console.log(first, third) const str = 'Hello' const [fst, , , , lst] = str console.log(fst, lst)

Phân rã biến cũng rất thường gặp khi bạn sử dụng ES6 module.

import { Component } from 'react' import { render } from 'react-dom'

Tính tương thích: Trừ IE11, tất cả các trình duyệt còn lại đều hỗ trợ.

6. Rest và spread

Rest — phần còn lại — là một bổ sung của phân rã biến mảng ở trên. Bạn dùng ba dấu chấm ... để biểu thị rest.

const [first, second, ...others] = [1, 2, 3, 4, 5] console.log(first, second, others)

Rest cũng được dùng khi khai báo hàm có thể nhận nhiều tham số

console.log(foo(1, 2, 3))

Bạn lưu ý biến args ở trên khác với biến đặc biệt arguments vốn có sẵn bên trong hàm. arguments là một đối tượng giống Array, với những thuộc tính đặc biệt như callee, trong khi args chỉ là một mảng bình thường.

Spread — rải — là thao tác ngược lại với rest, giúp bạn kết hợp một mảng đã có sẵn thành mảng mới.

const arr = [3, 4, 5] const newArr = [1, 2, chúng tôi 6] console.log(newArr)

Spread rất hữu ích để thay thế các thao tác thên mảng, như .concat().

const head = [1, 2] const tail = [3, 4, 5] console.log([...head, ...tail])

Spread cũng rất ngon khi thay thế cho Function.prototype.apply.

const params = [1, 2, 3] mul(...params)

Rest/spread cũng có thể hoạt động trên object, tương tự như Object.assign(), nhưng bạn lưu ý tính năng vẫn đang được đề xuất (proposal). Về phía trình duyệt, có Firefox và Chrome là hỗ trợ, trong khi Edge và Safari hoàn toàn không hoạt động.

const user = { name: 'John' } const userWithAgeEs5 = Object.assign({}, user, { age: 21 }) const userWithAge = { ...user, age: 21 } console.log(userWithAge) const { name, ...others } = userWithAge console.log(others)

Tính tương thích: Trừ IE11, tất cả các trình duyệt còn lại đều hỗ trợ rest và spread với mảng hay chuỗi. Với spread object, Edge và Safari chưa hỗ trợ.

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

Khi khai báo hàm, tính năng này cho phép bạn thiết lập giá trị mặc định của tham số khi nó không được truyền giá trị hoặc có giá trị undefined.

function getDiscountedPrice(price, discountRate = 0.1) { return price * (1 + discountRate) }

Dĩ nhiên bạn có thể dùng bất cứ giá trị nào làm giá trị mặc định.

function processItems(items = []) { return items.map(transformItemData) } const DISCOUNT_RATE = 0.1

8. Lớp (class)

Với ES5, chúng ta sử dụng function để tạo lớp và thêm các phương thức vào lớp bằng cách mở rộng prototype.

function Foo(x) { this.x = x } Foo.prototype.add = function(y) { return this.x + y } var f = new Foo(3) console.log(f.add(2))

ES6 mang đến cú pháp mới giúp tạo lớp trực tiếp và dễ dàng hơn.

class Foo { constructor(x) { this.x = x } add(y) { return this.x + y } static whoAmI() { return 'I am a Foo class' } } const f = new Foo(3) console.log(f.add(2)) console.log(Foo.whoAmI())

Bạn cũng có thể kế thừa từ lớp khác bằng từ khóa extends.

class Bar extends Foo { constructor(x, y) { super(x) this.y = y } calculate() { return this.add(4) + this.y } } const f = new Bar(3, 4) console.log(f.calculate())

Ngoài ra với bạn cũng có thể dùng hàm mũi tên khi khai báo phương thức trong lớp. Điều này giúp đảm bảo this luôn trỏ đến đối tượng hiện tại. Cú pháp này đặc biệt thông dụng trong các ứng dụng React, tuy nhiên vẫn chưa được hỗ trợ mặc định bởi các trình duyệt, nên bạn phải dùng Babel để chuyển đổi mã nguồn.

class Button extends React.Component { state = { name: 'Fabulous button' } e.preventDefault() } } } if (err) return reject(err) resolve(response) }) }) getUserData(123) .then(showUser)

Promise còn có các hàm tĩnh khác:

Promise.all(iterator)

Nhận vào một mảng các promises và chỉ resolve khi tất cả promises trong mảng được resolve.

Promise.race(iterator)

Nhận vào một mảng các promises và resolve/reject ngay khi một trong các promises trong mảng resolve/reject.

Promise.resolve()

Trả về một promise được tự động resolve.

Promise.reject()

Trả về một promise được tự động reject.

Tính tương thích: Trừ IE11, tất cả các trình duyệt còn lại đều hỗ trợ.

Kết

ES6 mang đến những tính năng tuyệt vời cho lập trình viên, giúp cho làm việc với JavaScript trở nên dễ thở hơn, đồng thời nâng cao hiệu suất, cải thiện mã nguồn và giảm dung lượng tập tin khi truyền tải trên mạng. Nếu ứng dụng của bạn hướng đến các trình duyệt hiện đại, đừng chần chờ gì, hãy dùng ES6 ngay hôm nay.

Bonus: Cheatsheet cho bạn nào làm biếng đọc 😉

Cùng Khám Phá Sức Mạnh Của Es6 Generators

Generators có thể xem như là cách áp dụng của iterables

Điều khiến generators trở nên đặc biệt bởi vì chúng là những functions có khả năng hoãn lại quá trình execution mà vẫn giữ nguyên được context.

Đây là một tính năng rất quan trọng khi ta phải dùng tới những executions đòi hỏi phải có quãng pause nhưng context phải được để nguyên nhằm để recover lại trong tương lai khi cần đến.  

Bạn có từng nghe qua quá trình phát triển async chưa?

Syntax – Cú pháp

Syntax (Cú pháp) cho generators bắt đầu với function* declaration của chính nó (nhớ lưu ý cái asterisk) và  yield dành cho khi generator muốn dừng (pause) execution.

function* generator() { yield 'foo' }

Với  next function, chúng ta có thể kiểm soát được quá trình tạo ra một generator từ  generator sẵn có.

Khi chạy  next function, thì code của  generator sẽ được thực hiện (execute) và cho đến khi gặp  yield thì sẽ ngừng lại.

Lúc đó,  yield sẽ xen vào và khiến cho  generator execution bị đình chỉ (pause).

const g = generator() g.next() g.next()

yield được sinh ra cùng lúc với generator và cho phép chúng ta đưa ra các giá trị mà mình muốn. Tuy nhiên, nó chỉ thực hiện được khi ở trong phạm vi của generator.

Nếu thử dùng yield  với một giá trị trong callback thì cho dù đã declared trong generator thì nó vẫn sẽ bị lỗi.

function* generator() { }

yield*

yield* được tạo ra nhằm có khả năng gọi một generator nằm trong một generator khác.

function* foo() { yield 'foo' } function* bar() { yield 'bar' foo() yield 'bar again' } const b = bar(); b.next() b.next() b.next()

Bạn có thể thấy b iterator, thuộc  bar  generator, không hề chạy như đúng ý ta khi call foo.

Đó là mặc dù foo  execution cho ra một iterator, nhưng ta sẽ không có lặp lại (iterate) nó được.

Vì thế mà ES6 cần có operator  yield*

function* bar() { yield 'bar' yield* foo() yield 'bar again' } const b = bar(); b.next() b.next() b.next() b.next()

Đồng thời nó cũng hoàn toàn có thể áp dụng với data consumers

for (let e of bar()) { console.log(e) } console.log([...bar()])

 yield* có khả năng kiểm tra và chạy qua hết tất cả ngõ ngách trong generator để yield ra phần nó cần.

function* bar() { yield 'bar' for (let e of foo()) { yield e } yield 'bar again' }

Generators cũng chính là Iterators

Generators thực chất là những iterables đơn giản. Nói cách khác chúng cũng sẽ theo luật của iterable và  iterator .

Luật của iterable cho ta biết một object sẽ nên return một function itera với key là  Symbol.iterator.

const g = generator() typeof g[Symbol.iterator]

Còn luật của iterator cho ta biết iterator nên là một object chỉ tới yếu tố tiếp theo của iteration. Object này phải chứa một function gọi là next

const iterator = g[Symbol.iterator]() typeof chúng tôi

Bởi vì generators là iterables nên chúng ta có thể dùng data consumer  for-of, để iterate (lặp lại) giá trị của generators (values).

for (let e of iterator) { console.log(e) }

Return

Chúng ta còn có thể add vào return cho generator, thế nhưng return sẽ hoạt động hơi khác đi tùy thuộc vào cách generators’ data được iterated.

function* generatorWithReturn() { yield 'foo' yield 'bar' return 'done' } var g = generatorWithReturn() g.next() g.next() g.next() g.next()

Khi ta thực hiện iteration bằng tay, sử dụng  next, sẽ nhận được returned value (i.e. done ) cũng chính là value cuối của iterator object và khi done  đưa ra kết quả true.

Mặt khác, khi sử dụng defined data consume như for-of hoặc destructuring thì returned value sẽ bị bỏ qua.

for (let e of g) { console.log(e) } console.log([...g])

yield*

Như bạn đã biết  yield* được tạo ra nhằm có khả năng gọi một generator nằm trong một generator khác.

Ngoài ra, nó còn cho phép chúng ta lưu trữ value returned bằng executed generator.

function* foo() { yield 'foo' return 'foo done' } function* bar() { yield 'bar' const result = yield* foo() yield result } for (let e of bar()) { console.log(e) }

Throw

Chúng ta có thể dùng throw trong một generator và next  sẽ truyền exception ra.

Và khi một exception bị đẩy ra, iterator (lặp) sẽ bị phá và state của nó sẽ được set thành  done: true

function* generatorWithThrow() { yield 'foo' throw new Error('Ups!') yield 'bar' } var g = generatorWithReturn() g.next() g.next() g.next()

Generators cũng chính là Data Consumers

Generators ngoài khả năng như một data producers, với yield, nó cũng có thể consume data khi dùng next.

function* generatorDataConsumer() { console.log('Ready to consume!') while (true) { const input = yield; console.log(`Got: ${input}`) } }

Có một vài điểm khá thú vị sau đây

var g = generatorDataConsumer() g.next() g.next('foo')

Generator Creation (1)

Ở stage này, chúng ta đang tạo ra generator g.

Và execution sẽ dừng lại tại điểm A.

Next đầu tiên (2)

Execution đầu tiên của next giúp cho generator được executed cho tới khi gặp phải yield.

Tất cả các giá trị (value) trong stage này khi đi qua  next sẽ bị lơ đi. Nguyên nhân là vì vẫn chưa có gặp một  yield nào cả.

Và execution của chúng ta chỉ dừng lại tại điểm B  khi một  value nào đó được đưa ra bởi  yield.

Next tiếp theo (3)

Lúc này thì value đã đi qua yieldvà như vậy execution sẽ bị ngừng lại.

Hãy dùng Cases

Implement Iterables

Bởi generators là một iterable implementation, khi chúng được tạo ra thì chúng ta cũng sẽ có một iterable object với từng yield đại diện cho một giá trị sẽ được đưa ra trên từng iteration. Nói cách khác chúng ta có thể dùng generators để tạo ra iterables.

Ví dụ sau đây sẽ thể hiện generator như là iterable  với khả năng lập một dãi các số nguyên cho tới khi nó đạt  max. Và ta cũng dùng for-of  để lập những giá trị trên.

Các bạn cũng cần lưu ý rằng yield sẽ khiến các execution bị dừng lại tại một điểm và các iteration sẽ khiến cho execution chạy tiếp tại các điểm đó.

function* evenNumbersUntil(max) { for (let value = 0; value <= max; value += 2) { if (value % 2 === 0) yield value; } } for (let e of evenNumbersUntil(10)) { console.log(e) }

Asynchronous Code

Ta còn có thể dùng generators  với những async code như  promises.

Tiện thể thì cũng coi như là để giới thiệu về async/await trên ES8.

function fetchStory() { get('story.json') .then(function (response) { return JSON.parse(response) }) .then(function (response) { console.log('Yey JSON!', response) }) }

Nhờ vào co library và một generator, code của chúng ta sẽ nhìn giống như synchronous code.

const fetchStory = co.wrap(function* () { try { const response = yield get('story.json') const text = yield JSON.parse(response) console.log('Yey JSON!', response) } })

Với async/await thì nó vẫn sẽ khá giống so với phiên bản trên

async function fetchStory() { try { const response = await get('story.json') const text = await JSON.parse(response) console.log('Yey JSON!', response) } }

Lời Kết

Generators chính là một cách thực hiện của iterable và nó dựa theo luật của  iterable của iterator . Vì thế mà chúng có thể dùng để tạo ra iterables.

Tính năng tuyệt vời nhất của Generator là khiến execution bị hoãn lại. Với  yield nếu xài ES6.

Không những thế với  yield*, ta còn có thể gọi một generator nằm trong một generator khác.

Generators chính là cách thức để giúp việc phát triễn không đồng bộ trở thành đồng bộ.

Nguồn: Topdev via Medium

Tìm Hiểu Cơ Bản Về Es6

1. ECMAScript ES6 là gì?

ES6 là chữ viết tắt của ECMAScript 6, là phiên bản mới nhất của chuẩn ECMAScript. ECMAScript do hiệp hội các nhà sản xuất máy tính Châu Âu đề xuất làm tiêu chuẩn của ngôn ngữ Javascript. Bạn cứ nghĩ xem hiện nay có khá nhiều trình duyệt Browser ra đời và nếu mỗi Browser lại có cách chạy Javascript khác nhau thì các trang web không thể hoạt động trên tất cả các trình duyệt đó được, vì vậy cần có một chuẩn chung để bắt buộc các browser phải phát triển dựa theo chuẩn đó.

ES6 ra đời vào năm 2015 nên cái tên ES2015 được lấy làm tên chính thức với nhiều tính năng mới học hỏi các ngôn ngữ cấp cao khác, hy vọng dần theo thời gian Javascript trở thành một ngôn ngữ lập trình hướng đối tượng.

Phiên bản sắp ra trong năm 2017 đó là phiên bản ES7 cũng đang được nghiên cứu và phát triển, họ cũng nhắm đến các kiến thức mới lạ như async function, observer, .. Hy vọng sẽ có nhiều biến động mới.

2. Các chức năng mới của ES6

Block Scoped: Định nghĩa biến với từ khóa let, cách định nghĩa này thì biến chỉ tồn tại trong phạm vi khối của nó (Block Scope)

Destructuring Assignments: Bạn có thể khởi tạo các biến từ một mảng bằng một dòng code đơn giản.

Default Parameters: Bạn có thể gán giá trị mặc định cho các tham số.

Template String: Tạo templaet HTML cực kì đơn giản

Weak, Set: các kiểu dữ liệu phức tạp mới

3. Arrow function

Cú pháp căn bản:

Cú pháp căn bản nhất của arrow function như sau:

ví dụ

4. Block Scoped

Block Scoped là gì:

Block Scoped là phạm vi trong một khối, nghĩa là chỉ hoạt động trong phạm vi được khai báo bời cặp {}.

ở Es6 người ta sử dụng biến let để khai báo cho biến trong cặp {}

xét ví dụ sau:

kết quả trả về sẽ là:

hello 1

hello 2

hello 3

hello 4

hello 5

– Vậy biến let so với var có gì khác biệt:

let tạo ra một biến chỉ có thể truy cập được trong block bao quanh nó, khác với var – tạo ra một biến có phạm vi truy cập xuyên suốt function chứa nó.

cũng cùng ví dụ về biến let ở trên nay ta sử dụng biến var:

nhưng ở biến var kết quả trả về sẽ là :

hello 5

hello 5

hello 5

hello 5

hello 5

Biến const : dùng để khai báo một hằng số – là một giá trị không thay đổi được trong suốt quá trình chạy.

ví dụ:

Chú ý:

Trong es6 hạn chế dùng biến var thay vào đó là ta dùng biến let

Nếu bạn sử dụng Jquery trong Es6 thì $(this) trong ES6 sẽ được hiểu là (window)

Để sửa chữa khi bạn sử dụng $(this) sẽ thay bằng $(e.currentTarget)

5. Babel.js

Babel.js là tool cuối cùng mình muốn giới thiệu với mọi người. Các bạn có thể viết code ES6 và dùng Repl của BabelJS để dịch lại sang mã ES5 chạy được trên browser. BabelJS mang lại khả năng phát triển và sử dụng các tính năng của ES6 ngay tại thời điểm này và chỉ cần thêm một thao tác compile là code sẽ chạy được trên các browser bình thường.

Qua bài này hy vọng bạn đã hiểu được sơ qua về ES6 là gì, hẹn gặp lại các bạn ở bài tiếp theo. Cảm ơn các bạn đã đọc bài viết này

All Rights Reserved

Bạn đang xem bài viết 10 Tính Năng Của Es6 (Ecmascript2015) Mọi Lập Trình Javascript Phải Biết trên website Tvzoneplus.com. Hy vọng những thông tin mà chúng tôi đã chia sẻ là hữu ích với bạn. Nếu nội dung hay, ý nghĩa bạn hãy chia sẻ với bạn bè của mình và luôn theo dõi, ủng hộ chúng tôi để cập nhật những thông tin mới nhất. Chúc bạn một ngày tốt lành!