一步一步似爪牙。html
學習es6以前咱們可能並不知道es6相比es5差距在哪, 可是這並不妨礙咱們站在巨人的肩膀上; 程序員就是要樂於嚐鮮;
學習es6最終目的是結合es5 一塊兒進行工程項目開發, 而不是徹底拋棄es5 ;
學習的方法是文檔爲主, 前人的blog爲輔助, 實際console爲最終標準 ;
注意!
號
留意TODO
關鍵詞node
http://mp.weixin.qq.com/s?__b...程序員
if (true) { console.log(a) // 報錯 : Uncaught ReferenceError: a is not defined(…) let a = 'js' } // 這裏也訪問不到 a
if(true){ var a = 1; if (true) { let a = 'js' // a == 'js' } a = 3; // a == 3; let a = 2 ; // 報錯Uncaught SyntaxError: Identifier 'a' has already been declared ; // 題外話, 在console中, 產生報錯後a的內存指引被清除, 能夠從新賦值 let a = 0; // a == 0 // 但實際開發中, 產生報錯, 後面的代碼再也不執行, 因此不會有這種狀況產生 }
const a = 1; a = 2; // 報錯 : Uncaught TypeError: Assignment to constant variable.(…)
const a = []; a.push(2) // a == [2] const b = {}; b.a = a ; // 包含了a數組的對象
if(true){ const c = 1; } // 此處訪問會報錯: Uncaught ReferenceError: c is not defined(…)
總結: 能夠把const理解爲let的常量版(不可改的let)es6
參考:
let [a, b, c] = [1, 2, 3]; // 即: let a = 1;let b = 2;let c = 3; let [bar, foo] = [1]; // 解構失敗: undefined // 即: let bar = 1; let foo = undefined let [a] = 1; // 等號的右邊不是數組 (或者嚴格地說,不是可遍歷的解構) // 報錯:VM2799:2 Uncaught TypeError: undefined is not a function(…) // 若是賦值的字面量全等undefined, 則默認值生效 let [x = 1] = [undefined];// x === 1 let [x = 1] = [];//x === 1 // null 不全等 undefined, 因此默認值不生效 let [x = 1] = [null];// x === null
// 解構賦值容許指定默認值。 let [foo = true] = []; // 即: foo === true
function f() { console.log('aaa'); } let [x = f()] = [1];// x === 1 // 此處f函數並無執行; 若是是es5, 在賦值過程當中, 確定會先執行f()方法: log('aaa') // es6 沒有執行f方法, 通過粗略查閱文檔, 百穀後, 並無獲得答案; 生命有限, 留待往後, TODO // 在與`MeatHill`老師交流事後,得知 , 在此處後面有具體的值,就不須要計算默認值, 賦值是從右往左運行
let [x = 1, y = x] = []; // x == 1; y == 1; let [x = 1, y = x] = [2]; // x == 2; y == 2; 別急, 一步一步來 // 第一步: x = 2(賦值從右到左, x = 1 不會計算); // 第二步: y = x = 2; let [x = 1, y = x] = [1, 2]; // 答案呢? 留着想 let [x = y, y = 1] = []; // 第一步 x = y ; y未聲明報錯
對象的解構與數組有一個重要的不一樣。數組的元素是按次序排列的,變量的取值由它的位置決定;而對象的屬性沒有次序,變量必須與屬性同名,才能取到正確的值。web
let { foo, bar } = { foo: "aaa", bar: "bbb" }; // 變量必須與屬性重名 // 以上實際上是 let { foo : foo, bar : bar } = { foo: "aaa", bar: "bbb" };的簡寫; // 對象的解構賦值的內部機制,是先找到同名屬性,而後再賦給對應的變量。真正被賦值的是後者,而不是前者 // foo === "aaa"; bar === "bbb" let {foo} = {bar: 'baz'}; // foo === undefined let arr = [1, 2, 3]; let {0 : first, [arr.length - 1] : last} = arr; // 數值也屬於對象的一種表現形式
let {x = 3} = {x: undefined}; // x === 3 // 默認值生效的條件是,對象的屬性值嚴格等於undefined。
let { foo: baz } = { foo: "aaa", bar: "bbb" }; // 上面代碼中,foo是匹配的模式,baz纔是變量。真正被賦值的是變量baz,而不是模式foo。
let obj = { p: [ 'Hello', { y: 'World' } ] }; let { p: [x, { y }] } = obj // 注意,這時p是模式,不是變量,所以不會被賦值。
let {foo: {bar}} = {baz: 'baz'}; // 報錯 : VM3721:2 Uncaught TypeError: Cannot match against 'undefined' or 'null'.(…) // 報錯 : 等號左邊對象的foo屬性,對應一個子對象。該子對象的bar屬性,解構時會報錯。緣由很簡單,由於foo這時等於undefined,再取子屬性就會報錯
let x;
{x} = {x: 1};
// 報錯: 由於JavaScript引擎會將{x}理解成一個代碼塊,從而發生語法錯誤。
// 應該不將大括號寫在行首,避免JavaScript將其解釋爲代碼塊, 正確的寫法:
let x;
({x} = {x: 1})面試
// 第三個參數默認值爲 {} function demo(a, b, {c , d} = {}){ console.log(a, b, c, d) // 1 2 'c' 'd' } demo(1, 2, {c : "c", d:"d"})
let [a, b, c, d, e] = 'hello' // a === 'h', b === 'e', ...... let {length} = 'hello'; // length === 5 // 相似數組的對象都有一個length屬性,所以還能夠對這個屬性解構賦值
小總結segmentfault
// 因此能夠交換變量的值 let x = 1; let y = 2; [x, y] = [y, x];
解構的意義數組
參考
概念瀏覽器
${}
關鍵詞let name = "Bob", time = "today"; console.log(`Hello ${name}, how are you ${time}?`) // 模板字符串都是用反引號表示,若是在模板字符串中須要使用反引號,則前面須要用反斜槓轉義
console.log(`string text line 1 string text line 2`); // "string text line 1 // string text line 2"
參考
function a(b, ...c){ console.log(b) // ["個人年齡是", ",個人性別是", "", raw: Array[3]] console.log(c) // Array : ["1", "nan"] } let d = "1"; a`個人年齡是${d},個人性別是${f}`
在標籤函數的第一個參數中,存在一個特殊的屬性raw ,咱們能夠經過它來訪問模板字符串的原始字符串app
傳統上,JavaScript只有indexOf方法,能夠用來肯定一個字符串是否包含在另外一個字符串中。ES6又爲String對象擴展了三種新方法。
參考
'Blue Whale'.includes('blue'); // return false 'Blue Whale'.includes('Whale' , 2); // return true
'Blue Whale'.startsWith('blue'); // return false 'Blue Whale'.startsWith('Whale' , 2); // return false 'Blue Whale'.startsWith('Whale' , 5); // return true
'Blue Whale'.endsWith('blue'); // return false 'Blue Whale'.endsWith('Whale' , 10); // return true '0Blue'.endsWith('Blue' , 5); // return true
之前es5 : function makeRequest(url, timeout, callback) { timeout = timeout || 2000; callback = callback || function() {}; // ... } 如今es6 : function makeRequest(url, timeout = 2000, callback = function(){}) { // ... }
若是不傳入參數, 或者傳入undefined, 則使用默認值;
參考:
console.log(...[1, 2, 3]) // 1 2 3 console.log(1, ...[2, 3, 4], 5); // 1 2 3 4 5
function func(x, y, z, a, b) { console.log(x, y, z, a, b); } var args = [1, 2]; func(0, ...args, 3, ...[4]); // 0 1 2 3 4
// es5使用數組做爲參數: function myFunction(x, y, z) { } var args = [0, 1, 2]; myFunction.apply(null, args); // es6使用數組做爲參數: function demo(x, y, z) { console.log(x, y, z) } var args = [0, 1, 2]; demo(...args);
let arr = [1, 2, 3]; let arr2 = [...arr]; // 就像是 arr.slice() arr2.push(4); console.log(arr2) // [1, 2, 3, 4] // arr 不受影響
var arr1 = [0, 1, 2]; var arr2 = [3, 4, 5]; var arr3 = [...arr1 , ...arr2] // arr3 : [0, 1, 2, 3, 4, 5]
var nodeList = document.querySelectorAll('div'); var array = [...nodeList]; // 實際: 360瀏覽器報錯 : VM2386:3 Uncaught TypeError: nodeList[Symbol.iterator] is not a function(…) // 版本: 8.7.0.306 // 火狐爲一個空數組 // 版本:26.0.0.137 // google爲undefined // 版本:57.0.2987.133
參考
剩餘參數只包含那些沒有對應形參的實參
function(a, b, ...restArgs) { // ...restArgs 即爲剩餘參數, 是一個Array對象 }
function fun1(...theArgs) { alert(theArgs.length); } fun1(); // 彈出 "0", 由於theArgs沒有元素 fun1(5); // 彈出 "1", 由於theArgs只有一個元素 fun1(5, 6, 7); // 彈出 "3", 由於theArgs有三個元素
// TODO
函數的name屬性,返回該函數的函數名。
這個屬性早就被瀏覽器普遍支持,可是直到 ES6 ,纔將其寫入了標準。
function foo() {} foo.name // "foo"
var a = function(){} a.name // 空字符串: "" let b = function(){} b.name // 一樣是 ""
解讀:
ES6 對這個屬性的行爲作出了一些修改。若是將一個匿名函數賦值給一個變量, ES5 的name屬性,會返回空字符串,而 ES6 的name屬性會返回實際的函數名。
但實際上國內目前主流瀏覽器支持的仍是es5爲主, 在node下搭建的es6環境, 纔會返回實際的函數名(Google測試已經支持)
let a = function d(demo){} a.name // "d"
重點:
!箭頭函數會捕獲其所在上下文的 this 值,做爲本身的 this 值
!也就是能夠理解爲: 箭頭函數沒有本身的this, 若是上下文沒有this, 則this指向Window對象
參考
let demoFun = oArgument => oDessert // demoFun 爲函數名 // oArgument 爲函數形參 // oDessert 爲返回的值 let func = (x, y) => { return x + y; }; //常規編寫 明確的返回值
let demoFun = (oArgument, drink) => oArgument + drink // 返回的是 oArgument + drink let demoFun = params => ({foo: bar}) //返回一個對象時,函數體外要加圓括號 let demoFun = (param1, param2, ...rest) => { statements } // 支持 剩餘參數和默認參數:
箭頭函數會捕獲其所在上下文的 this 值,做爲本身的 this 值,所以下面的代碼將如期運行。
function Person() { this.age = 0; setInterval(() => { // 回調裏面的 `this` 變量就指向了指望的那個對象了 this.age++; }, 3000); } var p = new Person();
var arr = () => arguments; arr(); // Uncaught ReferenceError: arguments is not defined(…)
var Foo = () => {}; var foo = new Foo(); // TypeError: Foo is not a constructor
var Foo = () => {}; console.log(Foo.prototype); // undefined
在箭頭函數中的箭頭不是操做符(或者運算符,就像'+ -'那些), 可是箭頭函數有特殊的解析規則就是:相比普通的函數,受操做符的優先級影響。參考: https://developer.mozilla.org...
let callback; callback = callback || function() {}; // ok callback = callback || () => {}; // SyntaxError:非法箭頭函數屬性 callback = callback || (() => {}); // ok
'use strict'; let obj = { i: 10, b: () => console.log(this.i, this), c: function() { console.log( this.i, this) } } obj.b(); // undefined, Window對象, 此處或許有疑問, 可翻閱?提過的`!` obj.c(); // 10, Object {...}
對象
let func = () => { foo: 1 }; // undefined
因此,記得用圓括號把文字表達式包起來:
var func = () => ({ foo: 1 });
箭頭u函數在某些狀況加仍是頗有便利的, 可是新的語法, 可讀性有所轉變, 要多使用, 多看才行
// TODO
參考:
https://developer.mozilla.org...
// TODO
Object.is() 方法肯定兩個值是不是 相同的值。
參考:
Object.is(value1, value2); // 返回一個布爾值
Object.is(NaN, NaN); // true Object.is(0, -0); // fasle Object.is(-0, +0) // false Object.is({},{}) // false var a = function () {}; var b = function () {}; Object.is(a, b) //false
NaN === NaN // false; 0 === -0 // true -0 === +0 // true {} === {} // false var a = function () {}; var b = function () {}; a === b //false
if (!Object.is) { Object.is = function(x, y) { // SameValue algorithm if (x === y) { // Steps 1-5, 7-10 // Steps 6.b-6.e: +0 != -0 return x !== 0 || 1 / x === 1 / y; } else { // Step 6.a: NaN == NaN return x !== x && y !== y; } }; }
Object.assign() 方法用於將全部可枚舉的屬性的值從一個或多個源對象複製到目標對象。它將返回目標對象。
// target目標對象。 // sources(多個)源對象。 Object.assign(target, ...sources)
var obj = { a: 1 }; var copy = Object.assign({}, obj); // {a: 1}
var o1 = { a: 1 }; var o2 = { b: 2 }; var o3 = { c: 3 }; var obj = Object.assign({},o1, o2, o3); // Object {a: 1, b: 2, c: 3}
var v1 = "abc"; var v2 = true; var v3 = 10; var v4 = Symbol("foo") var obj = Object.assign({}, v1, null, v2, undefined, v3, v4); // 原始類型會被包裝,null 和 undefined 會被忽略。 // 注意,只有字符串的包裝對象纔可能有自身可枚舉屬性。 console.log(obj); // { "0": "a", "1": "b", "2": "c" }
參考:
Object.setPrototypeOf() 方法設置一個指定的對象的原型 ( 即, 內部[[Prototype]]屬性)到另外一個對象或 null。
Object.setPrototypeOf(obj, prototype) // obj 要設置其原型的對象。. // prototype 該對象的新原型(一個對象 或 null).
var dict = Object.setPrototypeOf({}, null); // Object {}
參考
es6 能夠設置對象的__proto__
參考:
https://developer.mozilla.org...
super 關鍵字用於調用一個對象的父對象上的函數。
參考:
http://blog.csdn.net/kittyjie...
參考:
參考:
使用class
關鍵字聲明類
// 聲明一個類名爲 Rectangle 的JS類 // constructor方法用於建立和初始化使用一個類建立的一個對象。只容許存在一個 class Rectangle { constructor(height, width) { this.height = height; this.width = width; } }
類聲明不會聲明提高
類表達式能夠是被命名的或匿名的。
/* 匿名類 */ let Rectangle = class { constructor(height, width) { this.height = height; this.width = width; } }; /* 命名的類 */ let Rectangle = class Rectangle { constructor(height, width) { this.height = height; this.width = width; } };
若是沒有指定this, this值將爲undefined。
class Animal { speak() { return this; } static eat() { return this; } } let obj = new Animal(); let speak = obj.speak; speak(); // undefined let eat = Animal.eat; eat(); // undefined
"use strict" // 建立一個 Chef 類 class Chef { // 初始化 // 接收參數 constructor(food){ this.food = food; } cook(){ console.log(this.food) } } let qing = new Chef("?") qing.cook(); // ?
參考:
http://blog.csdn.net/qq_30100...
"use strict" // 建立一個 Chef 類 class Chef { // 初始化 // 接收參數 constructor(food){ this.food = food; this.dishs = []; } get menu(){ return this.dishs; } set menu(dishs){ this.dishs.push(dish) } cook(){ console.log(this.food) } } let qing = new Chef() console.log(qing.menu = "?") //? console.log(qing.menu = "❦") // ❦
"use strict" // 建立一個 Chef 類 class Chef { // 初始化 // 接收參數 constructor(food){ this.food = food; this.dishs = []; } get menu(){ return this.dishs; } set menu(dishs){ this.dishs.push(dish) } static cook(food){ console.log(food) } } // 不須要實例化Chef便可以直接使用 Chef.cook("?") // 輸出 : ?
"use strict" class Person{ constructor(name, birthday){ this.name = name this.birthday = birthday } intro(){ return `${this.name}, ${this.birthday}` } } // 使得Chef類 繼承 Person類 class Chef extends Person{ constructor(name, birthday){ // 調用父類的constructor函數 super(name, birthday) } } let qing = new Chef('qing', "1949-10-1"); // 實例化後纔可以使用 Chef類 的intro方法 qing.intro() // "qing, 1949-10-1"
參考:
Set 對象容許你存儲任何類型的惟一值,不管是原始值或者是對象引用。
new Set([iterable]); // iterable // 若是傳遞一個可迭代對象,它的全部元素將被添加到新的 Set中。 // 若是不指定此參數或其值爲null,則新的 Set爲空 // 返回值 // 一個新的Set對象。
let mySet = new Set(); mySet.add(1); // {1} mySet.add(5); // {1, 5} mySet.add("some text"); //{1, 5, "some text"} mySet.has(1); // true mySet.has(3); // false mySet.has(5); // true mySet.has(Math.sqrt(25)); // true mySet.has("Some Text".toLowerCase()); // true mySet.size; // 返回Set對象的值的個數 : 3 mySet.delete(5); // 從set中移除5並返回true mySet.delete(8); // 不存在8, 返回false mySet.has(5); // false, 5已經被移除 mySet.size; // 2, 咱們剛剛移除了一個值 // 按照插入順序,爲Set對象中的每個值調用一次callBackFn。若是提供了thisArg參數,回調中的this會是這個參數。 mySet.forEach(callbackFn[, thisArg]) // 與values()方法相同,返回一個新的迭代器對象,該對象包含Set對象中的按插入順序排列的全部元素的值。 mySet.keys() // 返回一個新的迭代器對象,該對象包含Set對象中的按插入順序排列的全部元素的值。 mySet.values() mySet.clear() // 清空所有值
var myArray = ["value1", "value2", "value3"]; // 用Set構造器將Array轉換爲Set var mySet = new Set(myArray); mySet.has("value1"); // returns true // 用...(展開操做符)操做符將Set轉換爲Array console.log([...mySet]); // 與myArray徹底一致
參考:
https://developer.mozilla.org...
Map 對象保存鍵值對。任何值(對象或者原始值) 均可以做爲一個鍵或一個值。
var myMap = new Map(); var keyObj = {}, keyFunc = function () {}, keyString = "a string"; // 添加鍵 myMap.set(keyString, "和鍵'a string'關聯的值"); myMap.set(keyObj, "和鍵keyObj關聯的值"); myMap.set(keyFunc, "和鍵keyFunc關聯的值"); myMap.size; // 3 // 讀取值 myMap.get(keyString); // "和鍵'a string'關聯的值" myMap.get(keyObj); // "和鍵keyObj關聯的值" myMap.get(keyFunc); // "和鍵keyFunc關聯的值" myMap.get("a string"); // "和鍵'a string'關聯的值" // 由於keyString === 'a string' myMap.get({}); // undefined, 由於keyObj !== {} myMap.get(function() {}) // undefined, 由於keyFunc !== function () {}
var myMap = new Map(); myMap.set(NaN, "not a number"); myMap.get(NaN); // "not a number"
Promise
, Class
, 期待ES8的異步函數(Async Functions)
;原文地址: https://segmentfault.com/a/11... 轉載無需聯繫, 但請著名來源 @SF.GG-Starch。程序員就是要勇於, 樂於嚐鮮;