摘要:將轉(zhuǎn)換成常見的使用實(shí)現(xiàn)的基于迭代器的迭代。處停止迭代器基于鴨子模型接口這里使用語法僅僅為了說明問題使用支持為了使用迭代器屬性需要引入。生成器是迭代器的子類,包含了附加的與。
概述原文地址:http://babeljs.io/docs/learn-...
本文基于Luke Hoban精妙的文章《es6features》,請把star獻(xiàn)給他,你可以在此嘗試這些特性REPL。
ECMAScript 2015 是 ECMAScript 在2015年6月正式發(fā)布的一套標(biāo)準(zhǔn)。ES2015是對語言的一次富有意義的更新,也是自2009年ES5標(biāo)準(zhǔn)發(fā)布以來,對于該門語言第一次主要的更新。主流JS引擎正在逐步完善對該標(biāo)準(zhǔn)的支持。
查看ECMAScript 2015的詳盡文檔
ECMAScript 2015的新特性 箭頭函數(shù)與詞法 this (Arrows and Lexical This)箭頭函數(shù)通過 => 語法簡化函數(shù)的書寫。其與C#,Java 8和CoffeeScript中相關(guān)特性有著相似的語法。同時(shí)支持表達(dá)式和語句。與函數(shù)不同,箭頭函數(shù)與上下文共享詞法作用域中的this
(注:為函數(shù)指ES5中函數(shù))
// 表達(dá)式 var odds = evens.map(v => v + 1); var nums = evens.map((v, i) => v + i); // 語句 nums.forEach(v => { if (v % 5 === 0) fives.push(v); }); // 詞法this var bob = { _name: "Bob", _friends: [], printFriends() { this._friends.forEach(f => console.log(this._name + " knows " + f)); } };類 Classes
ES2015中的類是一個(gè)基于面向?qū)ο笤玩溎J胶唵蔚恼Z法糖。通過簡單方便的聲明模式使得類模式更易用,并鼓勵(lì)交互操作。同時(shí),類支持基于原型鏈的繼承,super調(diào)用,實(shí)例與靜態(tài)方法,構(gòu)造函數(shù)。
(注:ES5中通過原型鏈模式來實(shí)現(xiàn)其他語言中通過類實(shí)現(xiàn)的邏輯,這種模式可以看作一種類模式)
class SkinnedMesh extends THREE.Mesh { constructor(geometry, materials) { super(geometry, materials); this.idMatrix = SkinnedMesh.defaultMatrix(); this.bones = []; this.boneMatrices = []; //... } update(camera) { //... super.update(); } static defaultMatrix() { return new THREE.Matrix4(); } }增強(qiáng)的Object字面量 Enhanced Object Literals
在ES6中對象被加強(qiáng)以支持諸如:構(gòu)造時(shí)的原型設(shè)定,簡化foo: foo聲明的寫法,定義方法,進(jìn)行super調(diào)用??傊@使得對象與類的聯(lián)系更加緊密,也讓基于對象的設(shè)計(jì)從中得到了同樣的便利。
var obj = { // 設(shè)置原型,"__proto__" or "__proto__" 寫法同樣適用 __proto__: theProtoObj, // Computed property name does not set prototype or trigger early error for // 復(fù)制 __proto__ 屬性 ["__proto__"]: somethingElse, // ‘handler: handler’格式的簡寫 handler, // 方法聲明 toString() { // Super 調(diào)用 return "d " + super.toString(); }, // 計(jì)算(動(dòng)態(tài)的)屬性名稱 [ "prop_" + (() => 42)() ]: 42 };
模版字符串 Template Strings__proto__ 屬性需要原生的支持(注:這里應(yīng)該指的是運(yùn)行環(huán)境的支持),并且在前代版本中是 不推薦 使用的。雖然大多數(shù)JS引擎現(xiàn)已支持該屬性,但還有一些并不支持。因此,只有在web瀏覽器需要屬性支持時(shí)才執(zhí)行該屬性,就像附件B中所述。在Node環(huán)境中也可以使用。
模版字符串是在構(gòu)造字符串時(shí)使用的語法糖,其與Perl,Python等語言中字符串插值特性類似。有選擇性的添加標(biāo)簽來定制字符串結(jié)構(gòu),這樣可以防止注入攻擊也能基于字符串去構(gòu)建更高層次的數(shù)據(jù)結(jié)構(gòu)。
// 基本字面量的創(chuàng)建 `This is a pretty little template string.` // 多行字符串 `In ES5 this is not legal.` // 綁定插值變量 var name = "Bob", time = "today"; `Hello ${name}, how are you ${time}?` // 非轉(zhuǎn)移的模版字符串 String.raw`In ES5 " " is a line-feed.` // 構(gòu)造一個(gè)HTTP格式的請求前綴用來解釋替換和構(gòu)造 GET`http://foo.org/bar?a=${a}&b=$ Content-Type: application/json X-Credentials: ${credentials} { "foo": ${foo}, "bar": ${bar}}`(myOnReadyStateChangeHandler);解構(gòu) Restructuring
解構(gòu)允許在綁定時(shí)使用模式匹配,其支持匹配數(shù)組與對象。與標(biāo)準(zhǔn)的foo["bar"]查詢類似,解構(gòu)是故障弱化的,即當(dāng)沒有匹配值時(shí)返回undefined
// 匹配數(shù)組 var [a, ,b] = [1,2,3]; a === 1; b === 3; // 匹配對象 var { op: a, lhs: { op: b }, rhs: c } = getASTNode() // 匹配對象簡寫 // 在作用域中綁定 `op`, `lhs` 與 `rhs` var {op, lhs, rhs} = getASTNode() // 作為參數(shù)使用的場景 function g({name: x}) { console.log(x); } g({name: 5}) // 故障弱化的解構(gòu) var [a] = []; a === undefined; // 有默認(rèn)值情況下的故障弱化的解構(gòu) var [a = 1] = []; a === 1; // 解構(gòu)與默認(rèn)參數(shù)聯(lián)用 function r({x, y, w = 10, h = 10}) { return x + y + w + h; } r({x:1, y:2}) === 23默認(rèn)參數(shù) Default,Rest參數(shù) Rest 及擴(kuò)展運(yùn)算符 Spread
設(shè)置被調(diào)用函數(shù)(callee)的默認(rèn)參數(shù)值。在函數(shù)調(diào)用時(shí),可將數(shù)組各項(xiàng)作為連續(xù)參數(shù)傳入。在函數(shù)末尾的參數(shù),可以綁定一個(gè)用數(shù)組傳入的不定長度的參數(shù)。Rest參數(shù)取代arguments更直接地應(yīng)用于常見例子中。
function f(x, y=12) { // 當(dāng)沒有輸入或輸入為undefined時(shí)y的值是12 return x + y; } f(3) == 15 function f(x, ...y) { // y是一個(gè)數(shù)組 return x * y.length; } f(3, "hello", true) == 6 function f(x, y, z) { return x + y + z; } // 將數(shù)組中的每一項(xiàng)作為參數(shù)傳入 f(...[1,2,3]) == 6Let與Const
let或const聲明后在解構(gòu)體中綁定 塊級作用域 。let是新版的var,const是單次賦值,靜態(tài)化限制了在const賦值后再對變量賦值。
function f() { { let x; { // 塊級作用域 const x = "sneaky"; // 報(bào)錯(cuò),不能改變常量 x = "foo"; } // x已由let創(chuàng)建 x = "bar"; // 報(bào)錯(cuò), 已經(jīng)用let創(chuàng)建過變量x let x = "inner"; } }迭代器與for..of循環(huán) (Iterators + For..Of)
迭代器對象允許像CLR IEnumerable或Java Iterable一樣定義迭代器。將for..in 轉(zhuǎn)換成常見的使用for..of實(shí)現(xiàn)的基于迭代器的迭代。不需要實(shí)現(xiàn)數(shù)組,支持如LINQ式的懶惰設(shè)計(jì)模式。
let fibonacci = { [Symbol.iterator]() { let pre = 0, cur = 1; return { next() { [pre, cur] = [cur, pre + cur]; return { done: false, value: cur } } } } } for (var n of fibonacci) { // 1000處停止 if (n > 1000) break; console.log(n); }
迭代器基于鴨子模型接口(這里使用TypeScript語法僅僅為了說明問題):
interface IteratorResult { done: boolean; value: any; } interface Iterator { next(): IteratorResult; } interface Iterable { [Symbol.iterator](): Iterator }
生成器 Generators使用 polypill 支持:為了使用迭代器屬性需要引入Babel polyfill。
通過使用function 與 yield,生成器簡化了迭代器的編寫。當(dāng)函數(shù)聲明時(shí)使用function格式時(shí)返回一個(gè)生成器實(shí)例。生成器是迭代器的子類,包含了附加的next與throw。這使得值可以回流進(jìn)生成器,所以yield是一個(gè)可以返回或拋出值的表達(dá)式。
值得注意的是在ES7的草案中,使用"await"同樣能夠達(dá)到這種異步編程的效果。
var fibonacci = { [Symbol.iterator]: function*() { var pre = 0, cur = 1; for (;;) { var temp = pre; pre = cur; cur += temp; yield cur; } } } for (var n of fibonacci) { // truncate the sequence at 1000 if (n > 1000) break; console.log(n); }
生成器接口定義(這里使用TypeScript語法僅僅為了說明問題):
interface Generator extends Iterator { next(value?: any): IteratorResult; throw(exception: any); }
Comprehensions使用 polypill 支持:為了使用迭代器屬性需要引入Babel polyfill。
在Babel6.0中已刪除
Unicode編碼非破壞性地添加以支持更全面的unicode,這包括:字符串中新的unicode字面量格式以及處理代碼斷點(diǎn)的新正則符號u,同時(shí),新的API可以在21位的級別上處理字符串。依賴這些新增的支持使得JavaScript構(gòu)建全球化應(yīng)用成為可能。
模塊 Modules從語言層面對組件定義模塊進(jìn)行支持。將主流的JavaScript模塊加載方式(AMD, CommonJS)變成標(biāo)準(zhǔn)。由運(yùn)行環(huán)境中的默認(rèn)加載器決定模塊運(yùn)行時(shí)的行為。直到獲取并執(zhí)行完請求的模塊,才執(zhí)行隱式異步模型中的代碼。
// lib/math.js export function sum(x, y) { return x + y; } export var pi = 3.141593; // app.js import * as math from "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"; export var e = 2.71828182846; export default function(x) { return Math.exp(x); } // app.js import exp, {pi, e} from "lib/mathplusplus"; console.log("e^π = " + exp(pi));
模塊的加載器 Module Loaders模塊模式:Babel可以將ES2015 編譯成多種不同的模式,諸如Common.js,AMD,System和UMD。你甚至可以創(chuàng)造你自己的模式。更多細(xì)節(jié)請參考
不存在于ES2015中:由于在之前的ES2015草案中被廢棄,其并未在ECMAScript2015年的規(guī)范中實(shí)現(xiàn)定義。不過目前這是一項(xiàng)正在進(jìn)行的工作,并且最終的標(biāo)準(zhǔn)將會(huì)寫入WHATWG"s Loader規(guī)則中。
模塊的加載器支持:
動(dòng)態(tài)加載 Dynamic loading
狀態(tài)隔離 State isolation
全局命名空間隔離 Global namespace isolation
可編譯的鉤子函數(shù) Compilation hooks
嵌套虛擬化技術(shù) Nested virtualization
默認(rèn)的模塊是可配置的,構(gòu)建的新模塊可以在孤立/受限的上下文代碼進(jìn)行代碼的求值和引用。
// 動(dòng)態(tài)加載 – ‘System’ 是默認(rèn)加載器 System.import("lib/math").then(function(m) { alert("2π = " + m.sum(m.pi, m.pi)); }); // 創(chuàng)建一個(gè)執(zhí)行沙盒即新的加載器 var loader = new Loader({ global: fixup(window) // 替代 ‘console.log’ }); loader.eval("console.log("hello world!");"); // 直接操控模塊的緩存 System.get("jquery"); System.set("jquery", Module({$: $})); // 警告:還未完成
需要添加polypill:由于Babel默認(rèn)使用common.js規(guī)范,所以并沒有包含polypill的模塊加載API。詳情查閱。
Map + Set + WeakMap + WeakSet使用模塊加載器:為了使用模塊加載器,需要告訴Babel使用模塊模式系統(tǒng)。同時(shí),確認(rèn)檢查System.js。
用于提高常見算法中數(shù)據(jù)結(jié)構(gòu)的高效性。
WeakMap接受對象作為鍵名(WeakMap的設(shè)計(jì)目的在于,鍵名是對象的弱引用(垃圾回收機(jī)制不將該引用考慮在內(nèi)),所以其所對應(yīng)的對象可能會(huì)被自動(dòng)回收。)
(注:紅字部分原文翻譯過來有點(diǎn)變扭,這里借用ES6入門的描述)
// Sets var s = new Set(); s.add("hello").add("goodbye").add("hello"); s.size === 2; s.has("hello") === true; // Maps var m = new Map(); m.set("hello", 42); m.set(s, 34); m.get(s) == 34; // Weak Maps var wm = new WeakMap(); wm.set(s, { extra: 42 }); wm.size === undefined // Weak Sets var ws = new WeakSet(); ws.add({ data: 42 }); // 由于添加的對象沒有別的引用,因此不會(huì)被set保留
代理 Proxies使用 polypill 支持:為了在所有環(huán)境中正常使用Map,Set,WeakMap和WeakSet需要引入Babel polyfill。
代理可以創(chuàng)建包括宿主對象所有可用行為的對象。其被應(yīng)用于攔截,對象虛擬化,日志/描述等多個(gè)方面。
// 代理一個(gè)普通對象 var target = {}; var handler = { get: function (receiver, name) { return `Hello, ${name}!`; } }; var p = new Proxy(target, handler); p.world === "Hello, world!"; // 代理一個(gè)函數(shù)對象 var target = function () { return "I am the target"; }; var handler = { apply: function (receiver, ...args) { return "I am the proxy"; } }; var p = new Proxy(target, handler); p() === "I am the proxy";
對于所有運(yùn)行級別的原操作,都有許多坑要注意:
var handler = { // target.prop get: ..., // target.prop = value set: ..., // "prop" in target has: ..., // delete target.prop deleteProperty: ..., // target(...args) apply: ..., // new target(...args) construct: ..., // Object.getOwnPropertyDescriptor(target, "prop") getOwnPropertyDescriptor: ..., // Object.defineProperty(target, "prop", descriptor) defineProperty: ..., // Object.getPrototypeOf(target), Reflect.getPrototypeOf(target), // target.__proto__, object.isPrototypeOf(target), object instanceof target getPrototypeOf: ..., // Object.setPrototypeOf(target), Reflect.setPrototypeOf(target) setPrototypeOf: ..., // for (let i in target) {} enumerate: ..., // Object.keys(target) ownKeys: ..., // Object.preventExtensions(target) preventExtensions: ..., // Object.isExtensible(target) isExtensible :... }
符號 Symbols無法支持的特性:由于ES5的局限,Proxies無法被編譯或polyfilled.詳見JavaScript引擎支持
符號能夠?qū)崿F(xiàn)對對象狀態(tài)的控制。字符串(與ES5中一致)與符號都能作為鍵來訪問屬性。符號是一種新的原始類型。可選的名稱參數(shù)可以用于調(diào)試,但并非特性的一部分。符號是獨(dú)一無二的(就像gensym生成的一樣)但并非是私有的,因?yàn)榭梢杂弥T如Object.getOwnPropertySymbols這樣的方法使它暴露出來。
(function() { // 模塊作用域符號 var key = Symbol("key"); function MyClass(privateData) { this[key] = privateData; } MyClass.prototype = { doStuff: function() { ... this[key] ... } }; // 在Babel中部分支持,全支持需要本地環(huán)境的實(shí)現(xiàn) typeof key === "symbol" })(); var c = new MyClass("hello") c["key"] === undefined
子類的構(gòu)建 Subclassable Built-ins通過polyfill實(shí)現(xiàn)有限支持:有限支持需要Babel polypill。由于語言的局限,一些特性無法被編譯或polyfilled。查閱core.js"s caveats部分獲得更多細(xì)節(jié).
在ES2015中像Array,Date和DOM元素都可以被繼承來構(gòu)建子類。
// 數(shù)組子類的用戶代碼 class MyArray extends Array { constructor(...args) { super(...args); } } var arr = new MyArray(); arr[1] = 12; arr.length == 2Math + Number + String + Object APIs
許多新加入的庫,包括核心數(shù)學(xué)工具庫,數(shù)組轉(zhuǎn)換助手與用于復(fù)制的 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("*")) // 返回一個(gè)真的數(shù)組 Array.of(1, 2, 3) // 與new Array(...)類似,但沒有單一參數(shù)的特殊表現(xiàn)。 [0, 0, 0].fill(7, 1) // [0,7,7] [1,2,3].findIndex(x => x == 2) // 1 ["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: new Point(0,0) })
二進(jìn)制與八進(jìn)制字面量 Binary and Octal Literals在polypill中有限的支持:這些APIs中大多數(shù) 都能通過Babel polypill實(shí)現(xiàn)支持。然而,某些對特性的支持由于一些原因被去掉了。(例如String.prototype.normalize需要一些額外的代碼來支持)詳情請參閱。
添加兩種新的數(shù)字字面量格式來支持二進(jìn)制(b)與十進(jìn)制(o)。
0b111110111 === 503 // true 0o767 === 503 // true
Promises僅支持字面量格式:Babel僅支持對0o767的轉(zhuǎn)換但并不支持Number("0o767")格式。
Promises是一個(gè)異步編程庫。 are a library for asynchronous programming. Promises是對那些將來可能被使用的值的第一類描述。Promises被使用在許多JavaScript庫中.
function timeout(duration = 0) { return new Promise((resolve, reject) => { setTimeout(resolve, duration); }) } var p = timeout(1000).then(() => { return timeout(2000); }).then(() => { throw new Error("hmm"); }).catch(err => { return Promise.all([timeout(100), timeout(200)]); })
Reflect API通過polyfill實(shí)現(xiàn)支持:為了實(shí)現(xiàn)Promises你必須引用Babel polypill。
完整的Reflect API通過對象暴露運(yùn)行級別的元操作。這實(shí)際上是一種反代理的API的模式,并允許調(diào)用與代理陷阱中相同的元操作。因此,在實(shí)現(xiàn)代理方面特別有用。
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){ this.c = a + b; } var instance = Reflect.construct(C, [20, 22]); instance.c; // 42
尾調(diào)用 Tail Calls通過polyfill實(shí)現(xiàn)支持:為了實(shí)現(xiàn)Reflect API你必須引用Babel polypill。
用在尾部的調(diào)用能保證棧不會(huì)無限地增長。使得遞歸算法在面對無限輸入時(shí)更加安全。
function factorial(n, acc = 1) { "use strict"; if (n <= 1) return acc; return factorial(n - 1, n * acc); } // 棧在現(xiàn)在大多數(shù)實(shí)現(xiàn)中會(huì)溢出 // 但在ES2015中對任何輸入都是安全的 factorial(100000)
在Babel 6中暫時(shí)性移除:由于其復(fù)雜性與全局支持尾調(diào)用產(chǎn)生的沖突,只有在明確自己指向尾部的遞歸方法時(shí)才能支持。由于其他一些bug被移除并將得到從新實(shí)現(xiàn)。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/80130.html
摘要:從最開始的到封裝后的都在試圖解決異步編程過程中的問題。為了讓編程更美好,我們就需要引入來降低異步編程的復(fù)雜性。異步編程入門的全稱是前端經(jīng)典面試題從輸入到頁面加載發(fā)生了什么這是一篇開發(fā)的科普類文章,涉及到優(yōu)化等多個(gè)方面。 TypeScript 入門教程 從 JavaScript 程序員的角度總結(jié)思考,循序漸進(jìn)的理解 TypeScript。 網(wǎng)絡(luò)基礎(chǔ)知識之 HTTP 協(xié)議 詳細(xì)介紹 HTT...
摘要:前端日報(bào)精選了解中的全局對象和全局作用域張鑫旭鑫空間鑫生活子進(jìn)程你應(yīng)該知道的一切直出內(nèi)存泄露問題的追查實(shí)踐我他喵的到底要怎樣才能在生產(chǎn)環(huán)境中用上模塊化騰訊前端大會(huì)大咖說大咖干貨,不再錯(cuò)過發(fā)布發(fā)布中文翻譯在使用進(jìn)行本地開發(fā)代碼 2017-07-07 前端日報(bào) 精選 了解JS中的全局對象window.self和全局作用域self ? 張鑫旭-鑫空間-鑫生活Node.js 子進(jìn)程:你應(yīng)該知道...
摘要:一般來說,聲明式編程關(guān)注于發(fā)生了啥,而命令式則同時(shí)關(guān)注與咋發(fā)生的。聲明式編程可以較好地解決這個(gè)問題,剛才提到的比較麻煩的元素選擇這個(gè)動(dòng)作可以交托給框架或者庫區(qū)處理,這樣就能讓開發(fā)者專注于發(fā)生了啥,這里推薦一波與。 本文翻譯自FreeCodeCamp的from-zero-to-front-end-hero-part。 繼續(xù)譯者的廢話,這篇文章是前端攻略-從路人甲到英雄無敵的下半部分,在...
摘要:以下例子的目的是使用來展示一個(gè)每秒都會(huì)更新的時(shí)鐘當(dāng)嘗試在的回調(diào)中使用來引用元素時(shí),很不幸,我們得到的只是一個(gè)屬于回調(diào)函數(shù)自身上下文的。 前言 胖箭頭函數(shù)(Fat arrow functions),又稱箭頭函數(shù),是一個(gè)來自ECMAScript 2015(又稱ES6)的全新特性。有傳聞?wù)f,箭頭函數(shù)的語法=>,是受到了CoffeeScript 的影響,并且它與CoffeeScript中的=>...
摘要:如果你的運(yùn)行緩慢,你可以考慮是否能優(yōu)化請求,減少對的操作,盡量少的操,或者犧牲其它的來換取性能。在認(rèn)識描述這些核心元素的過程中,我們也會(huì)分享一些當(dāng)我們構(gòu)建的時(shí)候遵守的一些經(jīng)驗(yàn)規(guī)則,一個(gè)應(yīng)用應(yīng)該保持健壯和高性能來維持競爭力。 一個(gè)開源的前端錯(cuò)誤收集工具 frontend-tracker,你值得收藏~ 蒲公英團(tuán)隊(duì)最近開發(fā)了一款前端錯(cuò)誤收集工具,名叫 frontend-tracker ,這款...
閱讀 2051·2021-10-08 10:05
閱讀 1892·2021-09-22 15:31
閱讀 3013·2021-09-22 15:13
閱讀 3492·2021-09-09 09:34
閱讀 2098·2021-09-03 10:46
閱讀 3128·2019-08-30 15:56
閱讀 1709·2019-08-30 15:53
閱讀 2364·2019-08-30 15:44