npm install -g babel npm install -g babel-node //提供基於node的REPL環境 //建立 .babelrc 文件 {"presets": ["es2015"]} npm install babel-presets-es2015
箭頭函數的用法相似phython
, coffeeScript
和 java8
php
//expression func body, (僅有1參數 括號可省略) var odds = evens.map(v => v+1); var nums = evens.map((v,i) => v + i); //statement func body nums.forEach( v => { if(v % 5 === 0){ fives.push(v); } }); //lexical this var sindy = { name: 'Sindy', friends: ['nami', 'robin'], printFriends() { //sindy.printFriends() this指向sindy, //forEach迭代函數內部this,跟它定義的上下文this一致 this.friends.forEach(f=>{ console.log(this.name + ' knows ' + f); }); } };
class
和 extend
是一種語法糖,也是基於原型繼承實現的。
class
支持 super calls
, 實例化,靜態方法和構造函數。java
//class聲明類 內部直接是屬性和方法 不用,分隔。 constructor class Person{ constructor(name, age){ this.name = name;//實例屬性 this.age = age; } sayhi(name){//原型對象的方法 console.log(this.name+' say hello to ' + name); } static like(){//靜態方法 console.log('i want to be freedom king'); } }
//繼承關鍵字 extends class Zoro extends Person{ constructor(fav){ super('zoro', 18); //constructor中, super引用父類的構造函數 this.fav = 'keep going'; // console.log(super); //error 不能直接打印super console.log(super('cici',9),'<--c'); } sayhi(){ // console.log(super); //error 不能直接打印super console.log(super.sayhi(),'<--m'); //原型對象的方法中, super引用父類的原型對象 super.sayhi();//調用父類原型對象的方法 } }
書寫對象字面量更方便簡潔。 如:foo:foo
的簡寫, 函數定義簡寫, 動態屬性名。node
var obj = { __proto__: theProtoObj, //設置原型對象 ['__proto__']: somethingElse, //['__proto__']表示計算的屬性名,不會認爲是設置原型對象, 有時也可避免提前報同名屬性的錯誤 handler, // hanlder: handler 的簡寫 toString(){//相似定義類 命名函數表達式的名稱做爲key //super calls return 'd' + super.toString(); //super 應該指向 theProtoObj }, ['prop_'+(()=>23)]: 23 //[expression] 中括號表示內部爲屬性名的計算表達式,可實現動態屬性名 }
__proto__
屬性在node下都支持,但在瀏覽器環境不必定都支持, chrome是支持的。es6
模板字符串跟php雙引號字符串相似 "hello ,$name"
,字符串中能夠解析變量和語句, 對於構造字符串是很方便的。chrome
//單行 `this is an alone night` //多行 `In ES5 this is not legal` //變量插值 var name = 'idle', time='today'; var greeting = `hello ${name}, how are you ${time}`; //不轉義 String.raw`in es5 "\n" is a line-feed`
參數解構 對象解構 數組解構, 解構是一種十分方便的語法特性. 當結構不對應解析失敗時,會對應的返回undefined,不報錯.typescript
//解構賦值 var [a, b] = [1,2]; // a===1, b===2 var {name, age} = getPerson(); //參數解構 function hello({name: x}){ console.log('hello, ', x); } hello({name: 'alice'}); //解構失敗 var [a] = []; // a===undefined //提供解構失敗時的默認值 var [a=1] = []; //a===1 //參數解構失敗的默認值 function r({x,y,w=10,h=20}){ return x+y+w+h; } r({x:1, y:2}); //參數默認值 function f(a, b=10){ return a+b; } f(5); //rest arguments function f(x,...y){//剩餘形參 // y is an array return x * y.length } f(3, 'hello', true);//6 function f(x,y,z){ return x+y+z; } f(...[2,3,4]); //=>9 剩餘實參
let
和 const
聲明的變量和常量都是屬於塊級做用域的.express
function f(){ let x; { const x = 'sindy'; //ok 由於塊級做用域 x = 'foo'; //error 由於x是常量 } x = 'bar'; //在let 以後賦值,沒問題 let x = 'inner'; //error 重複聲明 }
for .. of ..
迭代對象容許自定義迭代方式,如:npm
let fibonacci = { [Symbol.iterator]() { let pre=0, cur=1; return {//返回包含next方法的迭代對象(iterator) next(){ [pre, cur] = [cur, pre+cur]; return {done: false, value: cur}; //iteratorResult } } } }; for(var n of fibonacci){ if(n>100){//若無終止條件會一直迭代下去 n應該表明的是每次迭代的結果 break; } console.log(n); } //typescript風格的iterator接口定義 interface IteratorResult{ done: boolean, value: any } interface Iterator { next(): IteratorResult //包含next方法,且next()返回IteratorResult類型結果 } interface Iterable { [Symbol.iterator](): Iterator // fibonacci() 執行後返回Iterator }
function*
和 yield
, function*
聲明的函數返回一個generator實例. generator是iterator的子類型,它包含本身的throw
和next
編程
generator能夠實現await風格的異步編程api
//generator版的fibonacci var fibonacci = { [Symbol.iterator]: function*() {//function*聲明 var pre=0, cur=1; for(;;){//不會終止的循環? var temp = pre; pre = cur; cur += pre; yield cur;//generator實例每次執行都從yield的地方從新開始? } } }; for(var n of fibonacci){ if(n > 100){ break; } console.log(n); } //typescript風格的generator接口定義 interface generator extends iterator { next(value?: any): IteratorResult; //next方法可帶參數, yield返回參數給next? throw(exception: any); }
注意 iterator and generator 目前須要polyfill才能使用, 新版的chrome已支持.
// same as ES5.1 "𠮷".length == 2 // new RegExp behaviour, opt-in ‘u’ "𠮷".match(/./u)[0].length == 2 // new form "\u{20BB7}" == "𠮷" == "\uD842\uDFB7" // new String ops "𠮷".codePointAt(0) == 0x20BB7 // for-of iterates code points for(var c of "𠮷") { console.log(c); }
ES6有不一樣於amd
和 cmd
的模塊風格
//>lib/math.js export function sum(x,y){ return x + y; } export var fnum = 3.122323; //>app.js import * as math from 'lib/math'; console.log(math.sum, math.fnum); //>other.js import {fnum, sum} from 'lib/math'; //對象解構賦值 console.log(fnum, sum);
一些額外的特性 export default
和 export *
//>lib/otherMath.js export * from 'lib/math'; //導出math.js的接口 export var e = 2.323; export default function(x){ return Math.exp(x); } //>app.js import exp, {sum , e} from 'lib/otherMath';
var name = 'sindy'; var age = 20; //至關於node module.exports = {name:name, age:age}; export {name, age}; //至關於module.exports.default = function getName(){..} export default function getName(){ return name; }
//import m from './modA'; m === modA.export.default //import {name, age} from './modA' modA.exports 析構 import getName, {name, age} from './module-e.es'; console.log(name, age); console.log(getName());
//Sets var s = new Set(); s.add('hello').add('goodbye').add('hello');//已有則再也不加入 s.size === 2; //true //Maps var m = new Map(); m.set('hello', 'good'); m.set(s, 23); m.get(s) === 23; //WeakMap var wm = new WeakMap(); wm.set(s, {extra:24}); vm.size === undefined; //WeakSet var ws = new WeakSet(); ws.add({data:12});
攔截或代理對象的屬性讀寫,函數的調用。
//proxy a normal object var target = {};//被代理的對象 var handler = {//代理哪些方法 get: function(reciever, name){//get代理對屬性的訪問 return `hello, ${name}`; } }; var p = new Proxy(target, handler); p.world === 'hello, world'; //proxy a function object var target = function(){ console.log('i am the target'); }; var handler = { apply: function(reciever,...args){//代理 target() console.log('i am the proxy'); } }; //代理的類型 var handler = { //target.prop get: ..., //target.prop = val set: ..., //prop in target has: ..., //delete target.prop deleteProperty: ..., //target(args) apply: ..., //new target(args) constructor: ..., //Object.getOwnPropertyDescriptor(target, prop) getOwnPropertyDescriptor: ..., //Object.defineProperty(target, prop, descriptor) defineProperty: ..., //Object.getPrototypeOf(target), target.__proto__ //obj.isPrototypeOf(target), obj2 instanceof target getPrototypeOf: ..., //Object.setPrototypeOf(target, proto) setPrototypeOf: ..., //for(var i in target) enumerate: ..., //Object.keys(target) ownKeys: ..., //Object.preventExtensions(target) preventExtensions: ..., //Object.isExtensible(target) isExtensible: ... }
(function(){ //module scope symbol var key = Symbol('key'); function MyClass(privateData){ this[key] = privateData; } MyClass.prototype = { dostuff: function(){ ...this[key].. } }; typeof key === 'symbol'; })(); var c = new MyClass(); c['key'] === undefined;
Array
, Date
,Element
等成爲內置的子類。
class MyArray extends Array{ constructor(...args){ super(...args); } } var arr = new MyArray(); arr[1] = 12; arr.length === 2;
Number.isInterger(Ifinity); //false Number.isNaN('NaN'); //false Math.hypot(3,4); //5 'abcde'.includes('abc'); 'abc'.repeat(2); Array.from(document.querySelectAll('h2')); //return a real array Array.of(1,2,3); => [1,2,3] 枚舉數組元素的形式 建立數據, 同 new Array(1,2,3); 但沒有僅有1各參數時的歧義 [0,0,0].fill(7,1); //從index==1開始填充7 [1,2,3].findIndex(x=>x==2); //返回使迭代器爲真的元素的索引 ['a','b','c'].entries(); //iterator [0,'a'], [1,'b'], [2, 'c'] ['a','b','c'].keys(); //iterator 0,1,2 ['a','b','c'].values(); //iterator 'a','b','c' var alice = {name: 'Alice'}; Object.assign(alice, {age: 18}); //相似extend
0b111110111 === 503 0o767 === 503
Promise
是一個異步編程的庫,存在於不少其餘的JS庫中
function timeout(duration = 0){ return new Promise((resolve, reject) => {//返回稍後將被resolve的promise對象 setTimeout(resolve, duration);//定時resolve這個新new的promise }); } var p = timeout(1000).then(()=>{//promise鏈 return timeout(2000); }).then(()=>{ throw new Error('test'); }).catch(err=>{ return Promise.all([timeout(100), timeout(200)]); });
var o = {a: 1}; Object.defineProperty(o, 'b', {value:2}); o[Symbol('c')] = 3; Reflect.ownKeys(o); //['a','b',Symbol(c)] function C(a,b){ return this.c = a + b; } var instance = Reflect.construct(C, [10,12]); instance.c === 22;
防止stack overflow
function factorial(n, acc=1){//階乘計算 'use strict'; if(n <= 1){ return acc; } return factorail(n-1, n*acc); } factorail(10000); //尾調用優化後不會 stack overflow