【第1006期】ECMAScript 6 新特性
前言
ES8 都提出來了,今天給我看 ES6 會不會呵呵呢?
今日早讀文章由 @ 池盛星 翻譯分享。
正文從這開始~
ECMAScript 6, 也就是ECMAScript 2015, 是最新版的ECMAScript標準. ES6是JavaScript語言的重要更新, 同時也是自2009年的ES5以來的第一次正式更新. 目前, 主要的JavaScript引擎正在實現這些功能.
要查看完整的ES6標準規範, 請點擊ECMAScript 2015 Language Specification.
ES6包含以下新特性:
arrows
classes
enhanced object literals
template strings
destructuring
default + rest + spred
let + const
iterators + for..of
genetators
unicode
modules
module loaders
map + set + weakmap + weakset
proxies
symbols
subclassable built-ins
promises
math + number + string + array + object APIs
binary and octal literals
reflect api
tail calls
Arrows 箭頭函數
Arrows是函數的一種縮寫, 表現形式為=>. 它們在語法上, 類似於C#, Java 8以及CoffeeScript. 它們不僅支持塊級函數體, 同時也支持帶返回值的表達式函數體. 與普通函數的this作用域不同, 箭頭函數內部與它周圍代碼共享this作用域. 即, this指向同一個東西 .
// Expression bodies 表達式函數體
letodds=evens.map(v=>v+1);
letnums=evens.map((v,i)=>v+i);
letpairs=evens.map(v=>({even:v,odd:v+1}));
// Statement bodies 塊級函數體
nums.forEach(v=>{
if(v%5===){
fives.push(v);
}
});
// Lexical this: this 作用域
letbob={
_name:"Bob",
_friends:[],
printFriends(){
this._friends.forEach(f=>console.log(this._name+" knows "+f));
}
}
更多信息參考MDN: Arrow functions
Classes 類
ES6的類是基於prototype的OO模式的語法糖. 擁有簡單方便的聲明式格式, 使得類模式更易於使用, 並鼓勵互操作性. 類支持基於prototype的繼承, 超級調用(super calls), 實例(instance), 靜態方法(static methods)以及構造函數 .
// Classes
classSkinnedMeshextendsTHREE.Mesh{
constructor(geometry,metrials){
super(geometry,meterials);
this.idMatrix=SkinnedMesh.defaultMatrix();
this.bones=[];
this.boneMatrices=[];
// ...
}
update(camera){
// ...
super.update();
}
getboneCount(){
returnthis.bones.length;
}
setmatrixType(matrixType){
this.idMatrix=SkinnedMesh[matrixType]();
}
staticdefaultMatrix(){
returnnewTHREE.Matrix4();
}
}
更多信息參考MDN: Classes
Enhanced Object Literals 增強的對象字面量
對象字面量被擴展用於支持在構建時設置prototype, foo: foo的簡寫, 定義方法, 超級調用(super calls)以及使用表達式計算屬性名稱. 同時, 這些也將對象字面量和類聲明更緊密的結合在一起, 並使基於對象的設計獲得相同的便利 .
letobj={
// __proto__
__proto__:theProtoObj,
// Shorthand for `handler: handler`
handler,
// Methods
toString(){
// super calls
return"d "+super.toString();
},
// Computed (dynamic) property names
[ prop_ +(()=>42)]:42
}
更多信息請參考MDN: Grammar and types: Object literals
Template Strings 模板字元串
模板字元串(template strings)提供了一個構建字元串的語法糖. 這有點類似於Perl, Python以及其它類似語言的字元串插入功能. 作為一種選擇, 可以添加標籤(tag)以允許字元串在構建時被定製, 避免注入攻擊或者從字元串內容構建更高級別的數據結構 .
// 簡單字面量字元串
`In JavaScript
is a line-feed.`
// 多行字元串
`In JavaScript this is
not legal.`
// 字元串插值
letname="Bob";
lettime="today";
`Hello${name}, how are you${time}?`
// 構造一個HTTP請求前綴, 用於演繹替換和構造
POST`http://foo.org/bar?a=${a}&b=${b}
Content-type: application/json
X-Credentials:${credentials}
{"foo":${foo},
"bar":${bar}}`(myOnReadyStateChangeHandler);
更多信息請參考MDN: Template literals
Destructuring 解構
解構允許使用模式匹配進行綁定, 支持匹配數組和對象. 解構是故障弱化(指未匹配上時, 也不會出錯, 而是產生一個undefined值), 類似於標準對象查找foo["bar"], 當未找到時, 產生一個undefined 值 .
// list匹配
let[a,,b]=[1,2,3];
// a=1; b=3
// object匹配
let{op:a,lhs:{op:b},rhs:c}=getASTNode();
// object匹配簡寫
// 在scope內綁定`op`, `lhs`及`rhs`
let{op,lhs,rhs}=getASTNode();
// 可用於參數位置
functiong({name:x}){
console.log(x);// 5
}
g({name:5});
// 故障弱化解構
let[a]=[];
a===undefined;
// 故障弱化解構, 帶默認值
let[a=1]=[];
a===1;
更多信息請參考MDN: Destructuring assignment
Default + Rest + Spread 默認參數, 剩餘參數(Rest Parameters), Spread語法
為函數的參數設置默認值. 將傳入的參數的剩餘參數綁定到數組. 使用...操作符, 將數組解構成參數列表 .
// 給參數設置默認值
functionf(x,y=12){
// 如果沒有傳入y的值(或者傳入的是undefined), 那麼y就等於默認的值12
returnx+y;
}
f(3)===15
// 將傳入的參數的剩餘參數綁定到數組
functionf(x,...y){
// y是一個數組Array
returnx*y.length;
}
f(3,"hello",true)===6;
// 使用...操作符, 將數組解構成參數列表
functionf(x,y,z){
returnx+y+z;
}
// 傳入一個數組作為參數
f(...[1,2,3])===6;
更多信息請參考MDN: Default parameters, Rest parameters, Spread syntax
Let + Const
用let和const代替var, 定義塊級作用域的變數 .
functionf(){
letx;
{
// 由於let定義的是塊級作用域的變數, 所以這樣是合法的
constx="sneaky";
// 由於const定義的是常量, 所以不能再進行賦值操作
x="foo";
}
// 由於在函數f()內, 前面已經有let x的定義, 所以不能再次定義
// 報錯: Uncaught SyntaxError: Identifier x has already been declared
letx="inner";
}
更多信息請參考MDN: let, const
Iterators + for..of 迭代器 for..of
迭代器對象啟用自定義迭代, 如CLR IEnumberable或Java Iterable. 通用於for..in基於自定義迭代器的迭代, for..of用法類似. 不需要是一個真正的數組, 像LINQ一樣, 啟用懶設計模式 .
letfibonacci={
[Symbol.iterator](){
letpre=;
letcur=1;
return{
next(){
[pre,cur]=[cur,pre+cur];
return{done:false,value:cur}
}
}
}
}
for(varnoffibonacci){
// 在1000處截斷序列
if(n>1000){
break;
}
console.log(n);
}
迭代器對象啟用自定義迭代,如CLR IEnumerable或Java Iterable。 通用於...的自定義基於迭代器的迭代。 不需要實現陣列,實現LINQ等懶人設計模式。
更多信息請參考MDN: for...of
Generators
Generators使用function* 和yield簡化iterator-autoring. 聲明為function*的函數返回一個Generator實例. Generators是迭代器的子類型, 包括next和throw. 這些可能的值返回到generator, 因此yield是一個表達式, 它返回值或throws.
注意: 同時也可以用來啟用"await"類似的非同步編程, 請參閱ES7await 提案 .
letfibonacci={
[Symbol.iterator]:function*(){
letpre=;
letcur=1;
for(;;){
lettemp=pre;
pre=cur;
cur+=temp;
yieldcur;
}
}
}
for(letpoffibonacci){
// 在1000處截斷序列
if(n>1000){
break;
}
console.log(n);
}
使用generator介面:(使用TypeScript 語法)
interfaceGeneratorextendsIterator{
next(value?:any):IteratorResult;
throw(exception:any);
}
更多信息請參考MDN: Iteration protocols
Unicode
// same as ES5.1
"".length==2
// new RegExp behaviour, opt-in 『u』
"".match(/./u)[].length==2
// new form
"u"==""=="uD842uDFB7"
// new String ops
"".codePointAt()==0x20BB7
// for-of iterates code points
for(varcof""){
console.log(c);
}
Modules 模塊
語言級支持模塊化組件定義. 吸收流行的JavaScript模塊載入方式(AMD, CommonJS). 由host-defined默認載入器定義運行時行為. 隱式非同步模型 -- 在請求的模塊可用和處理之前, 不執行任何代碼 .
// lib/math.js
exportfunctionsum(x,y){
returnx+y;
}
exportletpi=3.141593;
// app.js
import*asmathfrom"lib/math";
console.log(`2π =${math.sum(math.pi,math.pi)}`);
// otherApp.js
import{sum,pi}from"lib/math";
console.log(`2π =${sum(pi,pi)}`);
其他更多的export default和export * 的功能:
// lib/mathPlusPlus.js
export*from"lib/math";
exportlete=2.71828182846;
exportdefaultfunction(x){
returnMath.log(x);
}
// app.js
importln,{pi,e}from"lib/mathPlusPlus";
console.log(`2π =${ln(e)*pi*2}`);
更多信息請參考MDN: import, export
Module Loaders 模塊載入器
模塊載入器支持:
Dynamic loading 動態載入
State isolation
Global namespace isolation
Complilation hooks
Nested virtualization
可用配置默認模塊載入器, 並且可以構造新的載入器以在隔離或約束上下文中評估和載入代碼 .
// Dynamic loading - "System" is default loader
System.import("lib/math").then(function(m){
console.log(`2π =${m.sum(m.pi,m.pi)}`);
});
// Create execution sandboxes - new Loaders
letloader=newLoader({
global:fixup(window)// replace "console.log"
});
loader.eval("console.log( hello world! );");
// Directly manipulate module cache
System.get( jquery );
System.set( jquery ,Module({$:$}));// 警告: 還沒有最終定稿
Map, Set, WeakMap, WeakSet
常用演算法的高效數據結構. WeakMaps提供了無密鑰(leak-free) object-key的side tables.
// Sets
lets=newSet();
s.add("hello").add("goodbye").add("hello");
// s.size === 2;
// s.has("hello") === true;
// Maps
letm=newMap();
m.set("hello",42);
m.set(s,34);
// m.get(s) === 34;
// Weak Sets
letws=newWeakSet();
ws.add({data:42});
// Weak Maps
letwm=newWeakMap();
wm.set(s,{extra:42});
// wm.size === undefined;
更多信息請參考MDN: Map, Set, WeakMap, WeakSet
Proxies 代理
代理可以創建具有可用於託管對象的全部行為的對象 .
// Proxying a normal object
lettarget={};
lethandler={
get:function(receiver,name){
return`Hello,${name}!`;
}
}
letp=newProxy(target,handler);
// p.world === `Hello, world!`;
// Proxying a function object
lettarget=function(){return`I am the target`;};
lethandler={
apply:function(receiver,...args){
return`I am the proxy.`;
}
}
letp=newProxy(target,handler);
// p() === `I am the proxy.`;
有可用於所有運行時元操作(meta-operations)的陷阱(traps):
varhandler=
{
get:...,
set:...,
has:...,
deleteProperty:...,
apply:...,
construct:...,
getOwnPropertyDescriptor:...,
defineProperty:...,
getPrototypeOf:...,
setPrototypeOf:...,
enumerate:...,
ownKeys:...,
preventExtensions:...,
isExtensible:...
}
更多信息請參考MDN: MDN Proxy
Symbols 一種新的原始數據類型
Symbols允許對象狀態的訪問控制. Symbols允許屬性是一個字元串(如ES5)或者symbol. Symbols是一種新的原始數據類型. 可選描述參數用於調試, 但不是身份的一部分. Symbols是唯一的(如gensym), 但不是私有的, 因為他們通過反射功能進行顯示, 如Object.getOwnPropertySymbols.
letMyClass=(function(){
// module scoped symbol
letkey=Symbol("key");
functionMyClass(privateData){
this[key]=privateData;
}
MyClass.prototype={
doStuff:function(){
// ...
this[key]
// ...
}
}
returnMyClass;
})();
letc=newMyClass("hello");
// c["key"] === undefined;
更多信息請參考MDN: Symbol
Subclassable Built-ins
在ES6中, 像Array, Date及DOM裡面的Element都可以被子類化(subclassed).
名為Ctor的函數的對象構造現在使用兩個階段(兩者都是實際派生的):
調用Ctor [@@create]分配對象,安裝任何特殊行為
調用新實例上的構造函數進行初始化
已知的@@create symbol可通過Symbol.create獲得。 內置函數現在顯式公開其@@create。
// Pseudo-code of Array
classArray{
constructor(...args){
/* ... */
}
static[Symbol.create](){
// Install special [[DefineOwnProperty]]
// to magically update length
}
}
// User code of Array subclass
classMyArrayextendsArray{
constructor(...args){
super(...args);
}
}
// Two-phase new :
// 1) Call @@create to allocate object
// 2) Invoke constructor on new instance
letarr=newMyArray();
arr[1]=12;
// arr.length === 2;
Math, Number, String, Array, Object APIs
新增了許多新的庫, 包括核心的Math庫, Array轉換助手, String助手以及用於copy的Object.assign.
Number.EPSILON
Number.isInteger(Infinity);// false
Number.isNaN("NaN");// false
Math.acosh(3);// 1.762747174039086
Math.hypot(3,4);// 5
Math.imul(Math.pow(2,32)-1,Math.pow(2,32)-2);// 2
"abcde".includes("cd");// true
"abc".repeat(3);// "abcabcabc"
Array.from(document.querySelectorAll("*"))// Returns a real Array
Array.of(1,2,3);// Similar to new Array(...), but without special one-arg behavior
[,,].fill(7,1);// [0, 7, 1]
[1,2,3].find(x=>x===3);// 3
[1,2,3].findIndex(x=>x===2);// 1
[1,2,3,4,5].copyWithin(3,);// [1, 2, 3, 1, 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"
Object.assign(Point,{origin:newPoint(,)});
Binary and Octal Literals 二進位和八進位
新添加兩個新的數字字面量格式: Binary(b)和Octal(o)
Promises
Promises是一個非同步編程庫. Promises是一個容器, 保存著某個未來才會結束的事件(通常是一個非同步操作)的結果. Promises已經在現在存在的JavaScript庫中被廣泛的使用.
functiontimeout(duration=){
returnnewPromise((resolve,reject)=>{
setTimeout(resolve,duration);
});
}
letp=timeout(1000).then(()=>{
returntimeout(2000);
}).then(()=>{
thrownewError("hmm");
}).catch(err=>{
returnPromise.all([timeout(100),timeout(200)]);
})
更多信息請參考MDN: Promise
Reflect API
Reflect對象與Proxy對象一樣,也是 ES6 為了操作對象而提供的新 API. 全反射API顯示了運行時(runtime-level)對象的元操作(meta-operations). 這實際上是Proxy API的逆向, 並允許進行與代理陷阱(proxy traps)相同的元操作(meta-operations)的調用.
請參考MDN: Reflect
Tail Calls 尾調用
指某個函數的最後一步是調用另一個函數. 尾部調用保證不會無限制地增長堆棧. 保證遞歸演算法面對無界輸入時的安全。
functionfactorial(n,acc=1){
use strict ;
if(n
returnacc;
}
returnfactorial(n-1,n*acc);
}
// Stack overflow in most implementations today,
// but safe on arbitrary inputs in ES6
factorial(100000);
關於本文
譯者:@池盛星
作者:@lukehoban
原文:https://github.com/lukehoban/es6features
點擊展開全文
※從移動端click到搖一搖
※你不應該錯過的前端技術會議
※Nodejs cluster模塊深入探究
※面向初學者的高階組件教程
※構建高性能展開&收縮動畫
TAG:前端早讀課 |
※181006《Give Me A Chance》MV預告的概念解析公開
※經典大黃靴還能這樣玩!Timberland Construct 10061企劃亮相!
※經典大黃靴還能這樣玩?!Timberland Construct 10061企劃亮相!
※【20181006diy美甲教程】可愛俏皮蝴蝶香水
※梵高日記20181006
※NO.1006 劉小美一你是我的玫瑰花
※【20181006美甲視頻】日系魔鏡粉水滴美甲
※我國西部最重要的國防公路G219,全長10065公里
※北川第1000個再生育家庭喜獲女嬰 系第1006個新生兒
※中科院1006件專利今年首次拍賣
※刺繡花朵圖案c1006的方法
※中科院將拍賣1006件專利 創歷史新高
※工信部擬收回中國網通10060客服碼號
※【每日星運】塔羅占卜1006運勢,12星座運勢早知道!
※【你求窩教-第1006期】油畫質感 浮雕花朵
※比爾蓋茨身價1006億美元,但他打算只給每個孩子留1000萬美元
※【20181006新款美甲】願你對過往的一切情深意重,但從不回頭。
※日運1006 | 巨蟹疑慮消除;天蠍表現亮眼
※官方緊急封禁1006個王者帳號:重點打擊高段位6排演員!
※天美封停1006個王者賬號,原來是因為夢淚!