ECMAScript6 新特性范例大全


Posted in Javascript onMarch 24, 2017

ECMAScript6 新特性范例大全

ECMAScript6(ECMAScript 2015 ,ES5,ES2016)技术已经在前端圈子很流行了,他给前端开发人员带来了很多惊喜,提供的语法糖使复杂的操作变得简单。

本文没有详细描述这些新特性,因为网上都已经有很多相关的介绍了。主要针对ES6 新特性收集了相关范例代码,他可以让你快速了解这个新的javascript规范。

箭头函数

function() 函数的简写表示法,但它不绑定 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();
 }
}

Lebab.io

增强的对象字面量

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

可在参数位置使用

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 -> []

参数默认值(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)

在函数中:

function f(x, y, z) {
 return x + y + z;
}
// 传递数组的每个元素作为参数
console.log(f(...[1,2,3]))

结果:

f(...[1,2,3]) -> 6

在数组中:

var parts = ["shoulders", "knees"];
var lyrics = ["head", ...parts, "and", "toes"]; 

console.log(lyrics)

结果:

lyrics -> ["head","shoulders","knees","and","toes"]

扩展 + 对象字面量

我们可以使用这个创造很酷的对象。

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 操作符来允许无限参数。

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)

迭代器是一个比数组更动态的类型。

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)

生成器创建迭代器,并且比迭代器更具动态性。他们不必以相同的方式跟踪状态 并不支持 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

一个产量的例子*

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 …;

Import Export

Set

Set 为数学对应,其中所有项目都是唯一的。对于知道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

Set

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

WeakSet

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

Map

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

WeakMap

代理(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:...
}

Proxy

Symbols

Symbols 是一个新类型。 可用于创建匿名属性。

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

更多信息

可继承内置函数

我们现在可以继承原生类。

class CustomArray extends Array {

}

var a = new CustomArray();

a[0] = 2
console.log(a[0])

结果:

a[0] -> 2

不能使用数组的代理(Proxy)来覆盖getter函数。

新类库

各种新的方法和常量。

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

二进制和八进制

二进制和八进制数字的字面量。

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 失败,allrace也将 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现有的还有一些新的方法。

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)优化

尾调用的概念非常简单,一句话就能说清楚,就是指某个函数的最后一步是调用另一个函数。

ES6可以确保尾调用不会造成堆栈溢出。 (不是所有的实现工作)。

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 相关文章推荐
动态控制Table的js代码
Mar 07 Javascript
firefox 和 ie 事件处理的细节,研究,再研究 书写同时兼容ie和ff的事件处理代码
Apr 12 Javascript
js 如何实现对数据库的增删改查
Nov 23 Javascript
js中 关于undefined和null的区别介绍
Apr 16 Javascript
javascript随机将第一个dom中的图片添加到第二个div中示例
Oct 08 Javascript
JavaScript获取网页中第一个链接ID的方法
Apr 03 Javascript
jQuery中 delegate使用的问题
Jul 03 Javascript
禁用backspace网页回退功能的实现代码
Nov 15 Javascript
bootstrap如何让dropdown menu按钮式下拉框长度一致
Apr 10 Javascript
微信小程序 生命周期函数详解
May 24 Javascript
JS实现的将html转为pdf功能【基于浏览器端插件jsPDF】
Feb 06 Javascript
react 组件传值的三种方法
Jun 03 Javascript
Three.js获取鼠标点击的三维坐标示例代码
Mar 24 #Javascript
jQuery插件FusionCharts实现的Marimekko图效果示例【附demo源码】
Mar 24 #jQuery
Node.js和Express简单入门介绍
Mar 24 #Javascript
js鼠标经过tab选项卡时实现切换延迟
Mar 24 #Javascript
详解angular2实现ng2-router 路由和嵌套路由
Mar 24 #Javascript
JS实现向iframe中表单传值的方法
Mar 24 #Javascript
JS正则替换去空格的方法
Mar 24 #Javascript
You might like
三个类概括PHP的五种设计模式
2012/09/05 PHP
用mysql_fetch_array()获取当前行数据的方法详解
2013/06/05 PHP
THINKPHP内容分页代码分享
2015/01/14 PHP
PHP mysqli事务操作常用方法分析
2017/07/22 PHP
javascript 必知必会之closure
2009/09/21 Javascript
javascript,jquery闭包概念分析
2010/06/19 Javascript
jquery ajax return没有返回值的解决方法
2011/10/20 Javascript
js清理Word格式示例代码
2014/02/13 Javascript
javascript实现禁止复制网页内容汇总
2015/12/30 Javascript
基于javascript实现最简单的选项卡切换效果
2016/05/16 Javascript
详解Vue.js分发之作用域槽
2017/06/13 Javascript
Vue props用法详解(小结)
2018/07/03 Javascript
vue3.0 CLI - 2.4 - 新组件 Forms.vue 中学习表单
2018/09/14 Javascript
使用jquery Ajax实现上传附件功能
2018/10/23 jQuery
Vue 2.0 侦听器 watch属性代码详解
2019/06/19 Javascript
JavaScript中的null和undefined用法解析
2019/09/30 Javascript
JavaScript实现移动小精灵的案例代码
2020/12/12 Javascript
[01:15:15]VG VS EG Supermajor小组赛B组胜者组第一轮 BO3第二场 6.2
2018/06/03 DOTA
python 顺时针打印矩阵的超简洁代码
2018/11/14 Python
python模糊图片过滤的方法
2018/12/14 Python
Python3删除排序数组中重复项的方法分析
2019/01/31 Python
Pandas删除数据的几种情况(小结)
2019/06/21 Python
Django跨域资源共享问题(推荐)
2020/03/09 Python
英国最大的在线时尚眼镜店:Eyewearbrands
2019/03/12 全球购物
求职简历中的自我评价分享
2013/12/08 职场文书
给全校老师的建议书
2014/03/13 职场文书
优秀家长事迹材料
2014/05/17 职场文书
中职生自荐信范文
2014/06/15 职场文书
乡村教师党员四风问题对照检查材料思想汇报
2014/10/08 职场文书
2014年统计工作总结
2014/11/21 职场文书
2015年医药代表工作总结
2015/04/25 职场文书
学历证明范文
2015/06/16 职场文书
《巨人的花园》教学反思
2016/02/19 职场文书
2019通用版新员工入职培训方案!
2019/07/11 职场文书
Python insert() / append() 用法 Leetcode实战演示
2021/03/31 Python
缓存替换策略及应用(以Redis、InnoDB为例)
2021/07/25 Redis