Babel 學(xué)習(xí) ES2015

2023-06-07 16:50 更新
ES6FEATURES
本文檔最初是從 Luke Hoban 的 es6features 倉庫轉(zhuǎn)載的。請到 GitHub 上給他 點個贊吧!
REPL
強烈建議在 REPL 上嘗試這些新功能。

簡介?

ECMAScript 2015 是一個 ECMAScript 標(biāo)準(zhǔn),于 2015 年 6 月批準(zhǔn)。

ES2015 是對 JavaScript 的重要更新,也是自 2009 年 ES5 標(biāo)準(zhǔn)化以來對該語言的第一次重大更新。主流 JavaScript 引擎對這些新特性的實現(xiàn) 正在進行中

參考 ES2015 標(biāo)準(zhǔn) 了解 ECMAScript 2015 的完整規(guī)范。

ECMAScript 2015 特性?

箭頭函數(shù)與 Lexical This?

箭頭函數(shù)是使用 => 語法的函數(shù)簡寫方式。他們在語法上 與 C#、Java 8 和 CoffeeScript 中的相關(guān)功能類似。他們都支持 表達式和both expression and statement bodies. Unlike functions, arrows share the same lexical this as their surrounding code. If an arrow is inside another function, it shares the "arguments" variable of its parent function.

JavaScript

// Expression bodies
var odds = evens.map(v => v + 1);
var nums = evens.map((v, i) => v + i);

// Statement bodies
nums.forEach(v => {
if (v % 5 === 0)
fives.push(v);
});

// Lexical this
var bob = {
_name: "Bob",
_friends: [],
printFriends() {
this._friends.forEach(f =>
console.log(this._name + " knows " + f));
}
};

// Lexical arguments
function square() {
let example = () => {
let numbers = [];
for (let number of arguments) {
numbers.push(number * number);
}

return numbers;
};

return example();
}

square(2, 4, 7.5, 8, 11.5, 21); // returns: [4, 16, 56.25, 64, 132.25, 441]

類(Class)?

ES2015 中的類(class)是在基于原型的面向?qū)ο竽J缴虾唵伟b的語法糖。擁有一個 單一且方便的聲明形式將更易于使用,并且 鼓勵混合使用。類(class)支持基于原型的繼承、super 調(diào)用、 實例和靜態(tài)方法以及構(gòu)造函數(shù)。

JavaScript

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();
}
}

Enhanced Object Literals?

Object literals are extended to support setting the prototype at construction, shorthand for foo: foo assignments, defining methods and making super calls. Together, these also bring object literals and class declarations closer together, and let object-based design benefit from some of the same conveniences.

JavaScript

var obj = {
// Sets the prototype. "__proto__" or '__proto__' would also work.
__proto__: theProtoObj,
// Computed property name does not set prototype or trigger early error for
// duplicate __proto__ properties.
['__proto__']: somethingElse,
// Shorthand for ‘handler: handler’
handler,
// Methods
toString() {
// Super calls
return "d " + super.toString();
},
// Computed (dynamic) property names
[ "prop_" + (() => 42)() ]: 42
};

警告

The proto property requires native support, and was deprecated in previous ECMAScript versions. Most engines now support the property, but some do not. Also, note that only web browsers are required to implement it, as it's in Annex B. It is available in Node.

模板字符串?

模板字符串為構(gòu)造字符串提供了語法糖。這 類似于 Perl、Python 等語言中的字符串插值功能。另外, tag can be added to allow the string construction to be customized, avoiding injection attacks or constructing higher level data structures from string contents.

JavaScript

// 創(chuàng)建基本的字符串字面量(literal string)
`This is a pretty little template string.`

// 多行字符串
`In ES5 this is
not legal.`

// 插入變量綁定的值
var name = "Bob", time = "today";
`Hello ${name}, how are you ${time}?`

// Unescaped template strings
String.raw`In ES5 "\n" is a line-feed.`

// Construct an HTTP request prefix is used to interpret the replacements and construction
GET`http://foo.org/bar?a=${a}&b=$
Content-Type: application/json
X-Credentials: ${credentials}
{ "foo": ${foo},
"bar": ${bar}}`(myOnReadyStateChangeHandler);

解構(gòu)(Destructuring)?

解構(gòu)(Destructuring)允許基于模式匹配的方式進行賦值,這種模式匹配能夠支持 數(shù)組(arrays)和對象(objects)。解構(gòu)采取的是弱化故障的處理策略,類似于標(biāo)準(zhǔn)的對象 查找 foo["bar"],在未找到時返回值為 undefined 。

JavaScript

// list matching
var [a, ,b] = [1,2,3];
a === 1;
b === 3;

// object matching
var { op: a, lhs: { op: b }, rhs: c }
= getASTNode()

// object matching shorthand
// binds `op`, `lhs` and `rhs` in scope
var {op, lhs, rhs} = getASTNode()

// Can be used in parameter position
function g({name: x}) {
console.log(x);
}
g({name: 5})

// Fail-soft destructuring
var [a] = [];
a === undefined;

// Fail-soft destructuring with defaults
var [a = 1] = [];
a === 1;

// Destructuring + defaults arguments
function r({x, y, w = 10, h = 10}) {
return x + y + w + h;
}
r({x:1, y:2}) === 23

Default + Rest + Spread?

Callee-evaluated default parameter values. Turn an array into consecutive arguments in a function call. Bind trailing parameters to an array. Rest replaces the need for arguments and addresses common cases more directly.

JavaScript

function f(x, y=12) {
// y is 12 if not passed (or passed as undefined)
return x + y;
}
f(3) == 15

JavaScript

function f(x, ...y) {
// y is an Array
return x * y.length;
}
f(3, "hello", true) == 6

JavaScript

function f(x, y, z) {
return x + y + z;
}
// Pass each elem of array as argument
f(...[1,2,3]) == 6

Let + Const?

限定在塊級作用域的變量定義方式。let 是新的 var。const 定義的變量只能被 賦值一次。靜態(tài)限制可以防止在賦值前使用。

JavaScript

function f() {
{
let x;
{
// 因為此變量是塊級作用域,因此是 ok 的
const x = "sneaky";
// 錯誤,定義的變量只能被賦值一次
x = "foo";
}
// 由于此變量是 `let` 定義的,因此是 ok 的
x = "bar";
// 錯誤,在同一塊級作用域中已經(jīng)被聲明過了
let x = "inner";
}
}

Iterators + For..Of?

Iterator 對象支持自定義迭代,就像 CLR 的 IEnumerable 或 Java 的 Iterable。利用 for..of 將 for..in 歸納為基于自定義迭代器的迭代。 不需要實現(xiàn)為一個數(shù)組,并且支持像 LINQ 一樣的懶設(shè)計模式(lazy design patterns)。

JavaScript

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) {
// truncate the sequence at 1000
if (n > 1000)
break;
console.log(n);
}

迭代(Iteration)就是基于這些假想類型的接口(使用 TypeScript 類型的語法僅用于闡述)實現(xiàn)的:

interface IteratorResult {
done: boolean;
value: any;
}
interface Iterator {
next(): IteratorResult;
}
interface Iterable {
[Symbol.iterator](): Iterator
}

通過 POLYFILL 提供支持

如需使用 Iterators 功能,則必須引入 Babel 的 polyfill。

Generators?

Generators simplify iterator-authoring using function* and yield. A function declared as function* returns a Generator instance. Generators are subtypes of iterators which include additional next and throw. These enable values to flow back into the generator, so yield is an expression form which returns a value (or throws).

Note: Can also be used to enable ‘a(chǎn)wait’-like async programming, see also ES7 await proposal.

JavaScript

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);
}

The generator interface is (using TypeScript type syntax for exposition only):

interface Generator extends Iterator {
next(value?: any): IteratorResult;
throw(exception: any);
}

SUPPORT VIA POLYFILL

In order to use Generators you must include the Babel polyfill.

Comprehensions?

在 Babel 6.0 中已刪除

Unicode?

持續(xù)完善對 Unicode 的全面支持,包括讓字符串支持新的 unicode 文本(literal) 以及正則表達式(RegExp)新增的 u 模式能夠支持 unicode 碼位(code point),還有新的 API 用以處理 21bit 碼位(code point)級別的字符串。這些新增的功能 讓 JavaScript 可以構(gòu)建全球化的應(yīng)用程序。

JavaScript

// 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);
}

模塊?

Language-level support for modules for component definition. Codifies patterns from popular JavaScript module loaders (AMD, CommonJS). Runtime behaviour defined by a host-defined default loader. Implicitly async model – no code executes until requested modules are available and processed.

JavaScript

// lib/math.js
export function sum(x, y) {
return x + y;
}
export var pi = 3.141593;

JavaScript

// app.js
import * as math from "lib/math";
console.log("2π = " + math.sum(math.pi, math.pi));

JavaScript

// otherApp.js
import {sum, pi} from "lib/math";
console.log("2π = " + sum(pi, pi));

Some additional features include export default and export *:

JavaScript

// lib/mathplusplus.js
export * from "lib/math";
export var e = 2.71828182846;
export default function(x) {
return Math.exp(x);
}

JavaScript

// app.js
import exp, {pi, e} from "lib/mathplusplus";
console.log("e^π = " + exp(pi));

MODULE FORMATTERS

Babel can transpile ES2015 Modules to several different formats including Common.js, AMD, System, and UMD. You can even create your own. For more details see the modules docs.

模塊加載器?

NOT PART OF ES2015

This is left as implementation-defined within the ECMAScript 2015 specification. The eventual standard will be in WHATWG's Loader specification, but that is currently a work in progress. What is below is from a previous ES2015 draft.

Module loaders support:

  • Dynamic loading
  • State isolation
  • Global namespace isolation
  • Compilation hooks
  • Nested virtualization

The default module loader can be configured, and new loaders can be constructed to evaluate and load code in isolated or constrained contexts.

JavaScript

// Dynamic loading – ‘System’ is default loader
System.import("lib/math").then(function(m) {
alert("2π = " + m.sum(m.pi, m.pi));
});

// Create execution sandboxes – new Loaders
var loader = new Loader({
global: fixup(window) // replace ‘console.log’
});
loader.eval("console.log(\"hello world!\");");

// Directly manipulate module cache
System.get("jquery");
System.set("jquery", Module({$: $})); // WARNING: not yet finalized

ADDITIONAL POLYFILL NEEDED

Since Babel defaults to using common.js modules, it does not include the polyfill for the module loader API. Get it here.

USING MODULE LOADER

In order to use this, you'll need to tell Babel to use the system module formatter. Also be sure to check out System.js.

Map + Set + WeakMap + WeakSet?

Efficient data structures for common algorithms. WeakMaps provides leak-free object-key’d side tables.

JavaScript

// 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 });
// Because the added object has no other references, it will not be held in the set

SUPPORT VIA POLYFILL

In order to support Maps, Sets, WeakMaps, and WeakSets in all environments you must include the Babel polyfill.

Proxy(代理)?

Proxy 能夠創(chuàng)建具有宿主對象全部可用功能的對象。 可用于攔截、對象虛擬化 日志/分析等。

JavaScript

// Proxying a normal object
var target = {};
var handler = {
get: function (receiver, name) {
return `Hello, ${name}!`;
}
};

var p = new Proxy(target, handler);
p.world === "Hello, world!";

JavaScript

// Proxying a function object
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";

所有運行時級別的元數(shù)據(jù)操作都提供了 trap(陷阱)功能:

JavaScript

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 :...
}

不支持的功能

受 ES5 所限,Proxy 功能無法進行代碼轉(zhuǎn)換或使用 polyfill。請參閱 各 JavaScript 引擎 的支持情況。

Symbols?

Symbols enable access control for object state. Symbols allow properties to be keyed by either string (as in ES5) or symbol. Symbols are a new primitive type. Optional name parameter used in debugging - but is not part of identity. Symbols are unique (like gensym), but not private since they are exposed via reflection features like Object.getOwnPropertySymbols.

JavaScript

(function() {

// module scoped symbol
var key = Symbol("key");

function MyClass(privateData) {
this[key] = privateData;
}

MyClass.prototype = {
doStuff: function() {
... this[key] ...
}
};

// Limited support from Babel, full support requires native implementation.
typeof key === "symbol"
})();

var c = new MyClass("hello")
c["key"] === undefined

LIMITED SUPPORT VIA POLYFILL

Limited support requires the Babel polyfill. Due to language limitations, some features can't be transpiled or polyfilled. See core.js's caveats section for more details.

可子類話的內(nèi)置對象?

在 ES2015 中,內(nèi)置對象 Array、Date 以及 DOM Element 可以子類化。

JavaScript

// User code of Array subclass
class MyArray extends Array {
constructor(...args) { super(...args); }
}

var arr = new MyArray();
arr[1] = 12;
arr.length == 2

部分支持

內(nèi)置對象是否可子類化要具體情況具體分析,例如 HTMLElement 可以 被子類化,而例如 Date、Array 和 Error 由于受 ES5 引擎的限制 不能 被子類化。

Math + Number + String + Object APIs?

Many new library additions, including core Math libraries, Array conversion helpers, and Object.assign for copying.

JavaScript

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
[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) })

LIMITED SUPPORT FROM POLYFILL

Most of these APIs are supported by the Babel polyfill. However, certain features are omitted for various reasons (e.g. String.prototype.normalize needs a lot of additional code to support). You can find more polyfills here.

二進制和八進制字面量?

增加了對二進制 (b) 和八進制 (o) 字面量的支持。

JavaScript

0b111110111 === 503 // true
0o767 === 503 // true

僅支持字面量(LITERAL)形式

Babel 只能轉(zhuǎn)換 0o767 而不能轉(zhuǎn)換 Number("0o767")。

Promises?

Promises 是一個異步編程用的工具庫。Promises 是第一種 對將來可以使用的值的類(class)的表示形式。Promises 被 用在大量已有的 JavaScript 工具庫中。

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)]);
})

通過 POLYFILL 提供支持

為了支持 Promise 功能,你必須引入 Babel 的 polyfill

反射 API?

Full reflection API exposing the runtime-level meta-operations on objects. This is effectively the inverse of the Proxy API, and allows making calls corresponding to the same meta-operations as the proxy traps. Especially useful for implementing proxies.

JavaScript

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

SUPPORT VIA POLYFILL

In order to use the Reflect API you must include the Babel polyfill.

尾部調(diào)用(Tail Calls)?

尾部調(diào)用不會讓棧(stack)無限制地增長。這讓 遞歸算法在面對不做限制的輸入時能夠安全執(zhí)行。

JavaScript

function factorial(n, acc = 1) {
"use strict";
if (n <= 1) return acc;
return factorial(n - 1, n * acc);
}

// 在如今的大部分實現(xiàn)中都將引起棧溢出(Stack overflow),
// 但是在 ES2015 中處理任意數(shù)量的輸入都是安全的
factorial(100000)

暫時從 BABEL 6 中刪除

由于支持全局尾部調(diào)用的復(fù)雜性和對性能的影響, 只支持顯式自引用方式的尾部遞歸(explicit self referencing tail recursion)。 由于其它 bug 的影響而將其刪除,并將重新實現(xiàn)。


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號