ECMAScript6 新特性范例大全

ECMAScript6(ECMAScript 2015 ,ES5,ES2016)技術已經(jīng)在前端圈子很流行了,他給前端開發(fā)人員帶來了很多驚喜,提供的語法糖使復雜的操作變得簡單。
本文沒有詳細描述這些新特性,因為網(wǎng)上都已經(jīng)有很多相關的介紹了。主要針對ES6 新特性收集了相關范例代碼,他可以讓你快速了解這個新的javascript規(guī)范。
箭頭函數(shù)
function() 函數(shù)的簡寫表示法,但它不綁定 this。
var odds = evens.map(v => v + 1); // no parentes and no brackets
var nums = evens.map((v, i) => v + i);
var pairs = evens.map(v => ({even: v, odd: v + 1}));
// Statement bodies
nums.forEach(v => {
if (v % 5 === 0)
fives.push(v);
});
this 是如何工作的?
var object = {
name: "Name",
arrowGetName: () => this.name,
regularGetName: function() { return this.name },
arrowGetThis: () => this,
regularGetThis: function() { return this }
}
console.log(this.name)
console.log(object.arrowGetName());
console.log(object.arrowGetThis());
console.log(this)
console.log(object.regularGetName());
console.log(object.regularGetThis());
結果:
this.name ->
object.arrowGetName() ->
object.arrowGetThis() -> [object Window]
this -> [object Window]
object.regularGetName() -> Name
object.regularGetThis() -> {"name":"Name"}
Classes(類)
我們知道“真正”語言中的類(Classes)。在 ES6 中類(Classes)其實是原型繼承的語法糖。
class SkinnedMesh extends THREE.Mesh {
constructor(geometry, materials) {
super(geometry, materials);
this.idMatrix = SkinnedMesh.defaultMatrix();
this.bones = [];
this.boneMatrices = [];
//...
}
update(camera) {
//...
super.update();
}
get boneCount() {
return this.bones.length;
}
set matrixType(matrixType) {
this.idMatrix = SkinnedMesh[matrixType]();
}
static defaultMatrix() {
return new THREE.Matrix4();
}
}
增強的對象字面量
var theProtoObj = {
toString: function() {
return "The ProtoOBject To string"
}
}
var handler = () => "handler"
var obj = {
// __proto__
__proto__: theProtoObj,
// Shorthand for ‘handler: handler'
handler,
// Methods
toString() {
// Super calls
return "d " + super.toString();
},
// Computed (dynamic) property names
[ "prop_" + (() => 42)() ]: 42
};
console.log(obj.handler)
console.log(obj.handler())
console.log(obj.toString())
console.log(obj.prop_42)
結果:
obj.handler -> () => "handler" obj.handler() -> handler obj.toString() -> d The ProtoOBject To string obj.prop_42 -> 42
字符串插值
字符串插值的好語法
字符串插值
var name = "Bob", time = "today";
var multiLine = `This
Line
Spans Multiple
Lines`
console.log(`Hello ${name},how are you ${time}?`)
console.log(multiLine)
結果:
`Hello ${name},how are you ${time}?` -> Hello Bob,how are you today?
multiLine -> This Line Spans Multiple Lines
解構 Destructuring
愚人碼頭注:列表匹配
// list "matching" var [a, , b] = [1,2,3]; console.log(a) console.log(b)
結果:
a -> 1 b -> 3
對象也能很好的解構
nodes = () => { return {op: "a", lhs: "b", rhs: "c"}}
var { op: a, lhs: b , rhs: c } = nodes()
console.log(a)
console.log(b)
console.log(c)
結果:
a -> a b -> b c -> c
使用速記表示法。
nodes = () => { return {lhs: "a", op: "b", rhs: "c"}}
// binds `op`, `lhs` and `rhs` in scope
var {op, lhs, rhs} = nodes()
console.log(op)
console.log(lhs)
console.log(rhs)
結果:
op -> b lhs -> a rhs -> c
可在參數(shù)位置使用
function g({name: x}) {
return x
}
function m({name}) {
return name
}
console.log(g({name: 5}))
console.log(m({name: 5}))
結果:
g({name: 5}) -> 5
m({name: 5}) -> 5
故障弱化解構
var [a] = [] var [b = 1] = [] var c = []; console.log(a) console.log(b); console.log(c);
結果:
a -> undefined b -> 1 c -> []
參數(shù)默認值(Default)
function f(x, y=12) {
return x + y;
}
console.log(f(3))
console.log(f(3,2))
結果:
f(3) -> 15 f(3,2) -> 5
擴展(Spread)
在函數(shù)中:
function f(x, y, z) {
return x + y + z;
}
// 傳遞數(shù)組的每個元素作為參數(shù)
console.log(f(...[1,2,3]))
結果:
f(...[1,2,3]) -> 6
在數(shù)組中:
var parts = ["shoulders", "knees"]; var lyrics = ["head", ...parts, "and", "toes"]; console.log(lyrics)
結果:
lyrics -> ["head","shoulders","knees","and","toes"]
擴展 + 對象字面量
我們可以使用這個創(chuàng)造很酷的對象。
let { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 };
console.log(x); // 1
console.log(y); // 2
console.log(z); // { a: 3, b: 4 }
// Spread properties
let n = { x, y, ...z };
console.log(n); // { x: 1, y: 2, a: 3, b: 4 }
console.log(obj)
可惜的是它還不支持:
npm install --save-dev babel-plugin-transform-object-rest-spread
Rest
我們可以使用 rest 操作符來允許無限參數(shù)。
function demo(part1, ...part2) {
return {part1, part2}
}
console.log(demo(1,2,3,4,5,6))
結果:
demo(1,2,3,4,5,6) -> {"part1":1,"part2":[2,3,4,5,6]}
Let
let是新的var。 因為它有塊級作用域。
{
var globalVar = "from demo1"
}
{
let globalLet = "from demo2";
}
console.log(globalVar)
console.log(globalLet)
結果:
globalVar -> from demo1 globalLet -> ReferenceError: globalLet is not defined
但是,它不會向window分配任何內容:
let me = "go"; // 全局作用域 var i = "able"; // 全局作用域 console.log(window.me); console.log(window.i);
結果:
window.me -> undefined window.i -> able
不能使用let重新聲明一個變量:
let me = "foo"; let me = "bar"; console.log(me);
結果:
SyntaxError: Identifier 'me' has already been declared
var me = "foo"; var me = "bar"; console.log(me)
結果:
me -> bar
Const
const 是只讀變量。
const a = "b" a = "a"
結果:
TypeError: Assignment to constant variable.
應該注意,const 對象仍然可以被改變的。
const a = { a: "a" }
a.a = "b"
console.log(a)
結果:
a -> {"a":"b"}
For..of
迭代器的新類型,可以替代for..in。 它返回的是值而不是keys。
let list = [4, 5, 6];
console.log(list)
for (let i in list) {
console.log(i);
}
結果:
list -> [4,5,6] i -> 0 i -> 1 i -> 2
let list = [4, 5, 6];
console.log(list)
for (let i of list) {
console.log(i);
}
結果:
list -> [4,5,6] i -> 4 i -> 5 i -> 6
迭代器(Iterators)
迭代器是一個比數(shù)組更動態(tài)的類型。
let infinite = {
[Symbol.iterator]() {
let c = 0;
return {
next() {
c++;
return { done: false, value: c }
}
}
}
}
console.log("start");
for (var n of infinite) {
// truncate the sequence at 1000
if (n > 10)
break;
console.log(n);
}
結果:
"start" -> start n -> 1 n -> 2 n -> 3 n -> 4 n -> 5 n -> 6 n -> 7 n -> 8 n -> 9 n -> 10
使用Typescript,我們可以看到它接口的樣子:
interface IteratorResult {
done: boolean;
value: any;
}
interface Iterator {
next(): IteratorResult;
}
interface Iterable {
[Symbol.iterator](): Iterator
}
生成器(Generators)
生成器創(chuàng)建迭代器,并且比迭代器更具動態(tài)性。他們不必以相同的方式跟蹤狀態(tài) 并不支持 done 的概念。
var infinity = {
[Symbol.iterator]: function*() {
var c = 1;
for (;;) {
yield c++;
}
}
}
console.log("start")
for (var n of infinity) {
// truncate the sequence at 1000
if (n > 10)
break;
console.log(n);
}
結果:
"start" -> start n -> 1 n -> 2 n -> 3 n -> 4 n -> 5 n -> 6 n -> 7 n -> 8 n -> 9 n -> 10
使用Typescript 再次顯示接口:
interface Generator extends Iterator {
next(value?: any): IteratorResult;
throw(exception: any);
}
function* Iterators and generator
一個產(chǎn)量的例子*
function* anotherGenerator(i) {
yield i + 1;
yield i + 2;
yield i + 3;
}
function* generator(i) {
yield i;
yield* anotherGenerator(i);
yield i + 10;
}
var gen = generator(10);
console.log(gen.next().value);
console.log(gen.next().value);
console.log(gen.next().value);
console.log(gen.next().value);
console.log(gen.next().value);
結果:
gen.next().value -> 10 gen.next().value -> 11 gen.next().value -> 12 gen.next().value -> 13 gen.next().value -> 20
Unicode
ES6 為Unicode 提供了更好的支持。
var regex = new RegExp('\u{61}', 'u');
console.log(regex.unicode)
console.log("\uD842\uDFD7")
console.log("\uD842\uDFD7".codePointAt())
結果:
regex.unicode -> true "" -> "".codePointAt() -> 134103
模塊和模塊加載器
原生支持模塊。
import defaultMember from "module-name";
import * as name from "module-name";
import { member } from "module-name";
import { member as alias } from "module-name";
import { member1 , member2 } from "module-name";
import { member1 , member2 as alias2 , [...] } from "module-name";
import defaultMember, { member [ , [...] ] } from "module-name";
import defaultMember, * as name from "module-name";
import "module-name";
export { name1, name2, …, nameN };
export { variable1 as name1, variable2 as name2, …, nameN };
export let name1, name2, …, nameN; // also var
export let name1 = …, name2 = …, …, nameN; // also var, const
export expression;
export default expression;
export default function (…) { … } // also class, function*
export default function name1(…) { … } // also class, function*
export { name1 as default, … };
export * from …;
export { name1, name2, …, nameN } from …;
export { import1 as name1, import2 as name2, …, nameN } from …;
Set
Set 為數(shù)學對應,其中所有項目都是唯一的。對于知道SQL的人來說,這相當于distinct。
var set = new Set();
set.add("Potato").add("Tomato").add("Tomato");
console.log(set.size)
console.log(set.has("Tomato"))
for(var item of set) {
console.log(item)
}
結果:
set.size -> 2
set.has("Tomato") -> true
item -> Potato
item -> Tomato
WeakSet
WeakSet對象允許您在集合中存儲弱持有的對象。沒有引用的對象將被垃圾回收。
var item = { a:"Potato"}
var set = new WeakSet();
set.add({ a:"Potato"}).add(item).add({ a:"Tomato"}).add({ a:"Tomato"});
console.log(set.size)
console.log(set.has({a:"Tomato"}))
console.log(set.has(item))
for(let item of set) {
console.log(item)
}
結果:
set.size -> undefined
set.has({a:"Tomato"}) -> false
set.has(item) -> true
TypeError: set[Symbol.iterator] is not a function
Map
Map 也稱為詞典。
var map = new Map();
map.set("Potato", 12);
map.set("Tomato", 34);
console.log(map.get("Potato"))
for(let item of map) {
console.log(item)
}
for(let item in map) {
console.log(item)
}
結果:
map.get("Potato") -> 12
item -> ["Potato",12]
item -> ["Tomato",34]
可以使用除字符串之外的其他類型。
var map = new Map();
var key = {a: "a"}
map.set(key, 12);
console.log(map.get(key))
console.log(map.get({a: "a"}))
結果:
map.get(key) -> 12
map.get({a: "a"}) -> undefined
WeakMap
使用鍵的對象,并且只保留對鍵的弱引用。
var wm = new WeakMap();
var o1 = {}
var o2 = {}
var o3 = {}
wm.set(o1, 1);
wm.set(o2, 2);
wm.set(o3, {a: "a"});
wm.set({}, 4);
console.log(wm.get(o2));
console.log(wm.has({}))
delete o2;
console.log(wm.get(o3));
for(let item in wm) {
console.log(item)
}
for(let item of wm) {
console.log(item)
}
結果:
wm.get(o2) -> 2
wm.has({}) -> false
wm.get(o3) -> {"a":"a"}
TypeError: wm[Symbol.iterator] is not a function
代理(Proxy)
代理可以用來改變對象的行為。 它們允許我們定義 trap 。
var obj = function ProfanityGenerator() {
return {
words: "Horrible words"
}
}()
var handler = function CensoringHandler() {
return {
get: function (target, key) {
return target[key].replace("Horrible", "Nice");
},
}
}()
var proxy = new Proxy(obj, handler);
console.log(proxy.words);
結果:
proxy.words -> Nice words
提供以下 trap :
var handler =
{
get:...,
set:...,
has:...,
deleteProperty:...,
apply:...,
construct:...,
getOwnPropertyDescriptor:...,
defineProperty:...,
getPrototypeOf:...,
setPrototypeOf:...,
enumerate:...,
ownKeys:...,
preventExtensions:...,
isExtensible:...
}
Symbols
Symbols 是一個新類型。 可用于創(chuàng)建匿名屬性。
var typeSymbol = Symbol("type");
class Pet {
constructor(type) {
this[typeSymbol] = type;
}
getType() {
return this[typeSymbol];
}
}
var a = new Pet("dog");
console.log(a.getType());
console.log(Object.getOwnPropertyNames(a))
console.log(Symbol("a") === Symbol("a"))
結果:
a.getType() -> dog
Object.getOwnPropertyNames(a) -> []
Symbol("a") === Symbol("a") -> false
可繼承內置函數(shù)
我們現(xiàn)在可以繼承原生類。
class CustomArray extends Array {
}
var a = new CustomArray();
a[0] = 2
console.log(a[0])
結果:
a[0] -> 2
不能使用數(shù)組的代理(Proxy)來覆蓋getter函數(shù)。
新類庫
各種新的方法和常量。
console.log(Number.EPSILON)
console.log(Number.isInteger(Infinity))
console.log(Number.isNaN("NaN"))
console.log(Math.acosh(3))
console.log(Math.hypot(3, 4))
console.log(Math.imul(Math.pow(2, 32) - 1, Math.pow(2, 32) - 2))
console.log("abcde".includes("cd") )
console.log("abc".repeat(3) )
console.log(Array.of(1, 2, 3) )
console.log([0, 0, 0].fill(7, 1) )
console.log([1, 2, 3].find(x => x == 3) )
console.log([1, 2, 3].findIndex(x => x == 2))
console.log([1, 2, 3, 4, 5].copyWithin(3, 0))
console.log(["a", "b", "c"].entries() )
console.log(["a", "b", "c"].keys() )
console.log(["a", "b", "c"].values() )
console.log(Object.assign({}, { origin: new Point(0,0) }))
結果:
Number.EPSILON -> 2.220446049250313e-16
Number.isInteger(Infinity) -> false
Number.isNaN("NaN") -> false
Math.acosh(3) -> 1.7627471740390859
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.of(1, 2, 3) -> [1,2,3]
[0, 0, 0].fill(7, 1) -> [0,7,7]
[1, 2, 3].find(x => x == 3) -> 3
[1, 2, 3].findIndex(x => x == 2) -> 1
[1, 2, 3, 4, 5].copyWithin(3, 0) -> [1,2,3,1,2]
["a", "b", "c"].entries() -> {}
["a", "b", "c"].keys() -> {}
["a", "b", "c"].values() -> TypeError: ["a","b","c"].values is not a function
Object.assign({}, { origin: new Point(0,0) }) -> ReferenceError: Point is not defined
文檔: Number, Math, Array.from, Array.of, Array.prototype.copyWithin, Object.assign
二進制和八進制
二進制和八進制數(shù)字的字面量。
console.log(0b11111) console.log(0o2342) console.log(0xff); // also in es5
結果:
0b11111 -> 31 0o2342 -> 1250 0xff -> 255
Promises
異步編程。
var p1 = new Promise((resolve, reject) => {
setTimeout(() => resolve("1"), 101)
})
var p2 = new Promise((resolve, reject) => {
setTimeout(() => resolve("2"), 100)
})
Promise.race([p1, p2]).then((res) => {
console.log(res)
})
Promise.all([p1, p2]).then((res) => {
console.log(res)
})
結果:
res -> 2 res -> ["1","2"]
快速的 Promise
var p1 = Promise.resolve("1")
var p2 = Promise.reject("2")
Promise.race([p1, p2]).then((res) => {
console.log(res)
})
結果:
res -> 1
快速失敗
如果一個 promise 失敗,all和race也將 reject(拒絕)。
var p1 = new Promise((resolve, reject) => {
setTimeout(() => resolve("1"), 1001)
})
var p2 = new Promise((resolve, reject) => {
setTimeout(() => reject("2"), 1)
})
Promise.race([p1, p2]).then((res) => {
console.log("success" + res)
}, res => {
console.log("error " + res)
})
Promise.all([p1, p2]).then((res) => {
console.log("success" + res)
}, res => {
console.log("error " + res)
})
結果:
"error " + res -> error 2 "error " + res -> error 2
反射(Reflect)
新類型的元編程與新的API現(xiàn)有的還有一些新的方法。
var z = {w: "Super Hello"}
var y = {x: "hello", __proto__: z};
console.log(Reflect.getOwnPropertyDescriptor(y, "x"));
console.log(Reflect.has(y, "w"));
console.log(Reflect.ownKeys(y, "w"));
console.log(Reflect.has(y, "x"));
console.log(Reflect.deleteProperty(y,"x"))
console.log(Reflect.has(y, "x"));
結果:
Reflect.getOwnPropertyDescriptor(y, "x") -> {"value":"hello","writable":true,"enumerable":true,"configurable":true}
Reflect.has(y, "w") -> true
Reflect.ownKeys(y, "w") -> ["x"]
Reflect.has(y, "x") -> true
Reflect.deleteProperty(y,"x") -> true
Reflect.has(y, "x") -> false
尾調用(Tail Call)優(yōu)化
尾調用的概念非常簡單,一句話就能說清楚,就是指某個函數(shù)的最后一步是調用另一個函數(shù)。
ES6可以確保尾調用不會造成堆棧溢出。 (不是所有的實現(xiàn)工作)。
function factorial(n, acc = 1) {
if (n <= 1) return acc;
return factorial(n - 1, n * acc);
}
console.log(factorial(10))
console.log(factorial(100))
console.log(factorial(1000))
console.log(factorial(10000))
console.log(factorial(100000))
console.log(factorial(1000000))
結果:
factorial(10) -> 3628800 factorial(100) -> 9.332621544394418e+157 factorial(1000) -> Infinity factorial(10000) -> Infinity factorial(100000) -> RangeError: Maximum call stack size exceeded factorial(1000000) -> RangeError: Maximum call stack size exceeded
原文:ES6 Features
相關文章
Javascript基礎教程之數(shù)據(jù)類型 (字符串 String)
javascript一共有9種數(shù)據(jù)類型,分別是字符串 String、數(shù)值型 Number、布爾型 Boolean、未定義 Undefine、空值 Null、對象 Object、引用Refernce、列表型 List、完成型 Completion,我們今天首先來看看(字符串 String)2015-01-01
JS特殊函數(shù)(Function()構造函數(shù)、函數(shù)直接量)區(qū)別介紹
函數(shù)是由這樣的方式進行聲明的:關鍵字 function、函數(shù)名、一組參數(shù),以及置于括號中的待執(zhí)行代碼;Function()構造函數(shù)實際上是功能完整的對象2013-05-05

