內容: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
命令,用來聲明變量。它的用法相似於var
,let所聲明的變量,只在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函數有多種理解角度:
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 又添加了Map
和Set
。這樣就有了四種數據集合,須要一種統一的接口機制,來處理全部不一樣的數據結構。
遍歷器(Iterator)就是這樣一種機制。它是一種接口,爲各類不一樣的數據結構提供統一的訪問機制。任何數據結構只要部署 Iterator 接口,就能夠完成遍歷操做
Iterator 的做用有三個:
for...of
循環,Iterator 接口主要供for...of
消費
(2)Iterator 的遍歷過程
next
方法,能夠將指針指向數據結構的第一個成員。next
方法,指針就指向數據結構的第二個成員。next
方法,直到它指向數據結構的結束位置。每一次調用next
方法,都會返回數據結構的當前成員的信息。具體來講,就是返回一個包含value
和done
兩個屬性的對象。其中,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之前:
ES 6以後:
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 }