瞭解ES6

內容:node

1.ES6介紹及基礎python

2.模塊、類和繼承es6

3.ES6高級特性編程

4.Generator和Iterator數組

5.異步編程promise

6.函數相關瀏覽器

 

內容參考:《ES6 標準入門》服務器

ES6標準閱讀連接:http://es6.ruanyifeng.com/數據結構

 

 

 

1、ES6介紹及基礎多線程

1.什麼是ES6

ECMAScript 6.0(如下簡稱 ES6)是 JavaScript 語言的下一代標準,已經在 2015 年 6 月正式發佈了。它的目標,是使得 JavaScript 語言能夠用來編寫複雜的大型應用程序,成爲企業級開發語言

 

 

2.JavaScript版本

JavaScript有不少版本,具體版本以下: 

 

 

3.let和const

(1)let

ES6 新增了let命令,用來聲明變量。它的用法相似於varlet所聲明的變量,只在let命令所在的代碼塊內有效,也就是說let建立塊級做用域

let和var的區別:

 1 {
 2   let a = 10;
 3   var b = 1;
 4 }
 5 
 6 console.log(a)  // ReferenceError: a is not defined.
 7 console.log(b)  // 1
 8 // 結果代表,let聲明的變量只在它所在的代碼塊有效
 9 
10 
11 // var和let的區別:
12 // 下面的代碼若是使用var,最後輸出的是10:
13 var a = [];
14 for (var i = 0; i < 10; i++) {
15   a[i] = function () {
16     console.log(i);
17   };
18 }
19 a[6]()  //  10
20 
21 
22 // 若是使用let,聲明的變量僅在塊級做用域內有效,最後輸出的是 6。
23 var a = [];
24 for (let i = 0; i < 10; i++) {
25   a[i] = function () {
26     console.log(i);
27   };
28 }
29 a[6]()  // 6

 

for循環的特別之處:

1 // 設置循環變量的那部分是一個父做用域,而循環體內部是一個單獨的子做用域
2 // 例以下面這段代碼:
3 for (let i = 0; i < 3; i++) {
4   let i = 'abc';
5   console.log(i);
6 }
7 // abc
8 // abc
9 // abc

 

另外,var命令會發生」變量提高「現象,即變量能夠在聲明以前使用,值爲undefined。這種現象多多少少是有些奇怪的,按照通常的邏輯,變量應該在聲明語句以後纔可使用。

爲了糾正這種現象,let命令改變了語法行爲,它所聲明的變量必定要在聲明後使用,不然報錯

1 // var 的狀況
2 console.log(foo); // 輸出undefined
3 var foo = 2;
4 
5 // let 的狀況
6 console.log(bar); // 報錯ReferenceError
7 let bar = 2;

 

(2)const

const聲明一個只讀常量;const一旦聲明就必須當即初始化,不能留到之後賦值;const做用域與let相同:只在所在的塊級做用域內有效

 1 const PI = 3.1415;
 2 PI  // 3.1415
 3 
 4 PI = 3;
 5 // TypeError: Assignment to constant variable.
 6 // 改變常量的值會報錯
 7 
 8 
 9 const foo;
10 // SyntaxError: Missing initializer in const declaration
// const 用來聲明一個不可賦值的變量  變量的值只能在聲明的時候賦予
const a = 1
a = 2 // 錯誤

// 下面的不是賦值 是操做 因此是能夠的
const arr = [1, 2]
arr.push(3)
// [1, 2, 3]

 

 

 

2、模塊、類和繼承

1.模塊module

歷史上,JavaScript 一直沒有模塊(module)體系,沒法將一個大程序拆分紅互相依賴的小文件,再用簡單的方法拼裝起來。其餘語言都有這項功能,好比 Ruby 的require、Python 的import,甚至就連 CSS 都有@import,可是 JavaScript 任何這方面的支持都沒有,這對開發大型的、複雜的項目造成了巨大障礙

在 ES6 以前,社區制定了一些模塊加載方案,最主要的有 CommonJS 和 AMD 兩種。前者用於服務器,後者用於瀏覽器。ES6 在語言標準的層面上,實現了模塊功能,並且實現得至關簡單,徹底能夠取代 CommonJS 和 AMD 規範,成爲瀏覽器和服務器通用的模塊解決方案;ES6 模塊的設計思想是儘可能的靜態化,使得編譯時就能肯定模塊的依賴關係,以及輸入和輸出的變量。CommonJS 和 AMD 模塊,都只能在運行時肯定這些東西。好比,CommonJS 模塊就是對象,輸入時必須查找對象屬性

 

ES6 模塊不是對象,而是經過export命令顯式指定輸出的代碼,再經過import命令輸入:

1 // export
2 export function stat() {}
3 export function exists() {}
4 export function readFile () {}
5 // import
6 import { stat, exists, readFile } from 'fs';

上面代碼的實質是從fs模塊加載 3 個方法,其餘方法不加載。這種加載稱爲「編譯時加載」或者靜態加載,即 ES6 能夠在編譯時就完成模塊加載,效率要比 CommonJS 模塊的加載方式高

 

模塊詳細內容:http://es6.ruanyifeng.com/#docs/module

 

 

2.類class

下面是ES5和ES6定義類的寫法:

 1 // ES5:
 2 function Point(x, y) {
 3   this.x = x;
 4   this.y = y;
 5 }
 6 
 7 Point.prototype.toString = function () {
 8   return '(' + this.x + ', ' + this.y + ')';
 9 };
10 
11 var p = new Point(1, 2);
12 
13 
14 //ES6:
15 class Point {
16   constructor(x, y) {
17     this.x = x;
18     this.y = y;
19   }
20 
21   toString() {
22     return '(' + this.x + ', ' + this.y + ')';
23   }
24 }

 

類詳細介紹:http://es6.ruanyifeng.com/#docs/class

 

 

3.繼承inherit

ES6中Class 能夠經過extends關鍵字實現繼承,這比 ES5 的經過修改原型鏈實現繼承,要清晰和方便不少

 1 class Point {
 2     constructor(x, y) {
 3         this.x = x;
 4         this.y = y;
 5     }
 6 }
 7 
 8 
 9 class ColorPoint extends Point {
10   constructor(x, y, color) {
11     super(x, y); // 調用父類的constructor(x, y)
12     this.color = color;
13   }
14 
15   toString() {
16     return this.color + ' ' + super.toString(); // 調用父類的toString()
17   }
18 }

 

繼承詳細內容:http://es6.ruanyifeng.com/#docs/class-extends

 

 

 

3、ES6高級特性

1.變量的解構賦值

ES6中容許這樣的賦值方式:

 1 let [a, b, c] = [1, 2, 3]
 2 
 3 let [foo, [[bar], baz]] = [1, [[2], 3]]; 4 foo // 1 5 bar // 2 6 baz // 3 7 8 let [ , , third] = ["foo", "bar", "baz"]; 9 third // "baz" 10 11 let [x, , y] = [1, 2, 3]; 12 x // 1 13 y // 3 14 15 let [head, ...tail] = [1, 2, 3, 4]; 16 head // 1 17 tail // [2, 3, 4] 18 19 let [x, y, ...z] = ['a']; 20 x // "a" 21 y // undefined 22 z // []

另外若是解析不成功,值就爲undefined,以下所示:

1 let [foo] = [];
2 let [bar, foo] = [1]; 3 // 以上兩種狀況都屬於解構不成功,foo的值都會等於undefined

更多細節:http://es6.ruanyifeng.com/#docs/destructuring

 

 

2.spread 和 rest

(1)拓展運算符spread

spread運算符用於數組的構造,析構,以及在函數調用時使用數組填充參數列表

 1 let arrs1 = ['aa', 'bb']
 2 let arrs2 = ['cc', 'dd']
 3 
 4 // 合併數組
 5 let arrs = [...arrs1, ...arrs2]
 6 console.log(arrs)  // ['aa', 'bb', 'cc', 'dd']
 7 
 8 // 析構數組
 9 let param1, param2
10 [param1, ...param2] = arrs1
11 
12 console.log(param1)  // aa
13 console.log(param2)  // ['bb']

 

(2)剩餘運算符rest

rest運算符用於獲取函數調用時傳入的參數

1 function testFunc(...args) {
2    console.log(args);  // ['aa', 'bb', 'cc']
3    console.log(args.length); // 3
4 }
5 // 調用函數
6 testFunc('aa', 'bb', 'cc'); 

剩餘運算符rest實現多參數:

1 function callFriends(via, ...friends) {
2   console.log('使用' + via + '通知: ' + friends.join(',') + '等' + friends.length + '個好友')
3 }
4 callFriends('QQ', '張三')
5 callFriends('電話', '張三', '李四', '王五')
6 
7 // 輸出結果:
8 // 使用QQ通知: 張三等1個好友
9 // 使用電話通知: 張三,李四,王五等3個好友

 

 

3.template

模板字符串(template string)是加強版的字符串,用反引號(`)標識。它能夠看成普通字符串使用,也能夠用來定義多行字符串,或者在字符串中嵌入變量

 1 // 傳統的 JavaScript 語言,輸出模板一般是這樣寫的(下面使用了 jQuery 的方法)。
 2 
 3 $('#result').append(
 4   'There are <b>' + basket.count + '</b> ' +
 5   'items in your basket, ' +
 6   '<em>' + basket.onSale +
 7   '</em> are on sale!'
 8 );
 9 
10 // 上面這種寫法至關繁瑣不方便,ES6 引入了模板字符串解決這個問題。
11 $('#result').append(`
12   There are <b>${basket.count}</b> items
13    in your basket, <em>${basket.onSale}</em>
14   are on sale!
15 `);

 

 

4.set和map

JavaScript中set和map這兩種數據結構詳細介紹:http://es6.ruanyifeng.com/#docs/set-map

(1)set

Set 在其餘語言裏面稱爲集合,是一種和 Array 類似的數據結構,不一樣之處在於, Set 中的元素都是不重複的,set 類型的主要做用是去重
用法以下:

 1 var s = new Set()
 2 
 3 // add 方法添加元素, 和 push 同樣
 4 s.add(1)
 5 s.add(2)
 6 
 7 // has 方法檢查元素是否在 set 中
 8 s.has(1) // true
 9 s.has(3) // false
10 
11 // size 屬性至關於 length
12 s.size  // 2
13 
14 // delete 方法刪除一個元素
15 s.delete(1)
16 s.has(1)
17 
18 s.size  // 1

注:JavaScript中的set不像python中的set那樣提供了一系列的運算方法,這些運算方法須要本身去實現

 

(2)map

Map 和 Object 很類似,在其餘語言中 一般會有 dict 和 object 兩種數據結構
如今 js 也有獨立的 dict 那就是 Map(其實沒多好用),其用法以下:

1 var m = new Map()
2 
3 // set 方法增長一個值
4 m.set('name', 'gua')
5 
6 // get 屬性獲得一個值
7 m.get('name')

 

 

 

4、Generator和Iterator和Decorator

1.generator 

(1)generator -> 相似python的生成器

Generator函數是 ES6 提供的一種異步編程解決方案,語法行爲與傳統函數徹底不一樣

Generator函數有多種理解角度:

  • 語法上,Generator 函數能夠理解爲是一個狀態機,封裝了多個內部狀態
  • 執行 Generator 函數會返回一個遍歷器對象即Generator 函數仍是一個遍歷器對象生成函數。返回的遍歷器對象可遍歷Generator函數內部的每一個狀態
  • 形式上Generator函數是一個普通函數,可是有兩個特徵。一是,function關鍵字與函數名之間有一個星號;二是,函數體內部使用yield表達式,定義不一樣的內部狀態(yield在英語裏的意思就是「產出」)

 

(2)generator函數語法

generator函數以下:

1 function* helloWorldGenerator() {
2   yield 'hello'
3   yield 'world'
4   return 'ending'
5 }
6 
7 var hw = helloWorldGenerator()

Generator 函數的調用方法與普通函數同樣,也是在函數名後面加上一對圓括號。不一樣的是,調用 Generator 函數後,該函數並不執行,返回的也不是函數運行結果,而是一個指向內部狀態的指針對象,也就是上一章介紹的遍歷器對象(Iterator Object)

下一步,必須調用遍歷器對象的next方法,使得指針移向下一個狀態。也就是說,每次調用next方法,內部指針就從函數頭部或上一次停下來的地方開始執行,直到遇到下一個yield表達式(或return語句)爲止。換言之,Generator 函數是分段執行的,yield表達式是暫停執行的標記,而next方法能夠恢復執行

 1 hw.next()
 2 // { value: 'hello', done: false }
 3 
 4 hw.next()
 5 // { value: 'world', done: false }
 6 
 7 hw.next()
 8 // { value: 'ending', done: true }
 9 
10 hw.next()
11 // { value: undefined, done: true }

 

關於generator詳細內容:http://es6.ruanyifeng.com/#docs/generator

 

 

2.iterator

(1)iterator -> 相似python中的迭代器

JavaScript 原有的表示集合的數據結構,主要是數組和對象,ES6 又添加了MapSet。這樣就有了四種數據集合,須要一種統一的接口機制,來處理全部不一樣的數據結構。

遍歷器(Iterator)就是這樣一種機制。它是一種接口,爲各類不一樣的數據結構提供統一的訪問機制。任何數據結構只要部署 Iterator 接口,就能夠完成遍歷操做

Iterator 的做用有三個:

  • 爲各類數據結構,提供一個統一的、簡便的訪問接口
  • 使得數據結構的成員可以按某種次序排列
  • ES6 創造了一種新的遍歷命令for...of循環,Iterator 接口主要供for...of消費

 

(2)Iterator 的遍歷過程

  • 建立一個指針對象,指向當前數據結構的起始位置。也就是說,遍歷器對象本質上,就是一個指針對象。
  • 第一次調用指針對象的next方法,能夠將指針指向數據結構的第一個成員。
  • 第二次調用指針對象的next方法,指針就指向數據結構的第二個成員。
  • 不斷調用指針對象的next方法,直到它指向數據結構的結束位置。

每一次調用next方法,都會返回數據結構的當前成員的信息。具體來講,就是返回一個包含valuedone兩個屬性的對象。其中,value屬性是當前成員的值,done屬性是一個布爾值,表示遍歷是否結束

下面是一個模擬next方法返回值的例子:

 1 var it = makeIterator(['a', 'b']);
 2 
 3 it.next() // { value: "a", done: false }
 4 it.next() // { value: "b", done: false }
 5 it.next() // { value: undefined, done: true }
 6 
 7 function makeIterator(array) {
 8   var nextIndex = 0;
 9   return {
10     next: function() {
11       return nextIndex < array.length ?
12         {value: array[nextIndex++], done: false} :
13         {value: undefined, done: true};
14     }
15   };
16 }

 

關於iterator詳細內容:http://es6.ruanyifeng.com/#docs/iterator

 

 

3.Decorator

(1)decorator -> 相似python中的裝飾器

許多面向對象的語言都有修飾器(Decorator)函數,用來修改類的行爲;裝飾器是一個對類進行處理的函數。裝飾器函數的第一個參數,就是所要修飾的目標類,固然也能夠不寫成函數調用的方式(見下面的代碼)

 1 @testable  // 等同於testable = testable(MyTestableClass)
 2 class MyTestableClass {
 3   // ...
 4 }
 5 
 6 function testable(target) {
 7   target.isTestable = true;
 8 }
 9 
10 MyTestableClass.isTestable // true
11 
12 // 上面代碼中,@testable就是一個修飾器
13 // 它修改了MyTestableClass類的行爲,爲它加上靜態屬性isTestable。testable函數的參數target是MyTestableClass類自己

 

(2)decorator修飾類的屬性

 1 class Person {
 2   @readonly
 3   name() { return `${this.first} ${this.last}` }
 4 }
 5 
 6 function readonly(target, name, descriptor){
 7   // descriptor對象原來的值以下
 8   // {
 9   //   value: specifiedFunction,
10   //   enumerable: false,
11   //   configurable: true,
12   //   writable: true
13   // };
14   descriptor.writable = false;
15   return descriptor;
16 }
17 
18 readonly(Person.prototype, 'name', descriptor);
19 // 相似於
20 Object.defineProperty(Person.prototype, 'name', descriptor);

 

關於decorator的詳細內容:http://es6.ruanyifeng.com/#docs/decorator

 

 

 

5、異步編程

1.JavaScript中的異步編程

至少在語言級別上,Javascript是單線程的,所以異步編程對其尤其重要。

拿nodejs來講,外殼是一層js語言,這是用戶操做的層面,在這個層次上它是單線程運行的,也就是說咱們不能像Java、Python這類語言在語言級別使用多線程能力。取而代之的是,nodejs編程中大量使用了異步編程技術,這是爲了高效使用硬件,同時也能夠不形成同步阻塞。不過nodejs在底層實現其實仍是用了多線程技術,只是這一層用戶對用戶來講是透明的,nodejs幫咱們作了幾乎所有的管理工做,咱們不用擔憂鎖或者其餘多線程編程會遇到的問題,只管寫咱們的異步代碼就好

ES 6之前:

  • 回調函數
  • 事件監聽(事件發佈/訂閱)
  • Promise對象

ES 6以後:

  • Generator函數(協程coroutine)
  • async和await

 

 

2.callback(回調函數)

假定有兩個函數f1和f2,後者等待前者的執行結果:

1 f1();
2 f2();

若是f1是一個很耗時的任務,能夠考慮改寫f1,把f2寫成f1的回調函數:

1 function f1(callback){
2     setTimeout(function () {
3         // f1的任務代碼
4         callback();
5     }, 1000);
6 }

執行代碼就變成這樣:f1(f2);

採用這種方式,咱們把同步操做變成了異步操做,f1不會堵塞程序運行,至關於先執行程序的主要邏輯,將耗時的操做推遲執行。

回調函數的優勢是簡單、容易理解和部署,缺點是不利於代碼的閱讀和維護,各個部分之間高度耦合,流程會很混亂,並且每一個任務只能指定一個回調函數

 

 

3.promise

ES 6中原生提供了Promise對象,Promise對象表明了某個將來纔會知道結果的事件(通常是一個異步操做),而且這個事件對外提供了統一的API,可供進一步處理。
使用Promise對象能夠用同步操做的流程寫法來表達異步操做,避免了層層嵌套的異步回調,代碼也更加清晰易懂,方便維護。

 

 

4.async函數

ES2017 標準引入了 async 函數,使得異步操做變得更加方便。async 函數是什麼?一句話,它就是 Generator 函數的語法糖

詳細內容直接看這裏:http://es6.ruanyifeng.com/#docs/async

 

 

 

6、函數相關

1.函數參數默認值(函數默認參數)

1 // ES6 容許爲函數的參數設置默認值,即直接寫在參數定義的後面:
2 function log(x, y = 'World') {
3   console.log(x, y);
4 }
5 
6 log('Hello') // Hello World
7 log('Hello', 'China') // Hello China
8 log('Hello', '') // Hello

 

 

2.箭頭函數

箭頭函數就是匿名函數定義的簡化版, 宣稱能使得代碼更簡潔,實際上就是純粹的垃圾
箭頭函數的 this 值是綁定了的,箭頭函數沒有 arguments 對象,若是要多參數, 必須用 ...

語法以下:

 1 // (參數1, 參數2) => { 語句 }
 2 // (參數1, 參數2) => 語句
 3 // 上面兩行至關於下面這函數
 4 function(參數1, 參數2) {
 5     return 語句
 6 }
 7 
 8 // 若是隻有一個參數,圓括號可省略的
 9 // (參數1) => { 語句 }
10 // 參數1 => { 語句 }
11 
12 // 可是若是沒有參數, 必須須要使用圓括號
13 // () => { 語句 }
14 
15 // 例子
16 var a1 = [1, 2, 3]
17 // 下面兩個等價
18 var a2 = a1.map(function(n){
19     return n * n
20 })
21 var a3 = a1.map( n => n * n )
22 
23 n => n * n
24 // 上面 1 行等價於下面 3 行
25 function(n) {
26     return n * n
27 }
相關文章
相關標籤/搜索