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 相关文章推荐
建议大家看下JavaScript重要知识更新
Jul 08 Javascript
javascript 放大镜 v1.0 基于Yui2 实现的放大镜效果
Mar 08 Javascript
Wordpress ThickBox 点击图片显示下一张图的修改方法
Dec 11 Javascript
js简单实现HTML标签Select联动带跳转
Oct 23 Javascript
JavaScript中用getDate()方法返回指定日期的教程
Jun 09 Javascript
jQuery右下角旋转环状菜单特效代码
Aug 10 Javascript
利用jQuery和CSS将背景图片拉伸
Oct 16 Javascript
纯javascript实现自动发送邮件
Oct 21 Javascript
动态更新highcharts数据的实现方法
May 28 Javascript
JavaScript关于提高网站性能的几点建议(一)
Jul 24 Javascript
JS获取当前使用的浏览器名字以及版本号实现方法
Aug 19 Javascript
使用jQuery给Table动态增加行、清空table的方法
Sep 05 jQuery
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错误Allowed memory size of 67108864 bytes exhausted的3种解决办法
2014/07/28 PHP
thinkphp框架实现删除和批量删除
2016/06/29 PHP
PHP实现的链式队列结构示例
2017/09/15 PHP
PHP 中魔术常量的实例详解
2017/10/26 PHP
使用Git实现Laravel项目的自动化部署
2019/11/24 PHP
一段实时更新的时间代码
2006/07/07 Javascript
图片自动更新(说明)
2006/10/02 Javascript
JavaScript DOM学习第一章 W3C DOM简介
2010/02/19 Javascript
在iframe里的页面编写js,实现在父窗口上创建动画效果展开和收缩的div(不变动iframe父窗口代码)
2011/12/20 Javascript
JQuery的$和其它JS发生冲突的快速解决方法
2014/01/24 Javascript
js对文章内容进行分页示例代码
2014/03/05 Javascript
javascript查询字符串参数的方法
2015/01/28 Javascript
分享经典的JavaScript开发技巧
2015/11/21 Javascript
jquery.form.js框架实现文件上传功能案例解析(springmvc)
2016/05/26 Javascript
基于JS实现无缝滚动思路及代码分享
2016/06/07 Javascript
JavaScript获取中英文混合字符串长度的方法示例
2017/02/04 Javascript
微信小程序 开发之顶部导航栏实例代码
2017/02/23 Javascript
使用socket.io实现简单聊天室案例
2018/01/02 Javascript
在vue项目中引用Iview的方法
2018/09/14 Javascript
Mpvue中使用Vant Weapp组件库的方法步骤
2019/05/16 Javascript
taro小程序添加骨架屏的实现代码
2019/11/15 Javascript
微信小程序实现上传照片代码实例解析
2020/08/04 Javascript
基于Vue全局组件与局部组件的区别说明
2020/08/11 Javascript
详解JavaScript 事件流
2020/09/02 Javascript
解决Vue keep-alive 调用 $destory() 页面不再被缓存的情况
2020/10/30 Javascript
深入理解Python中变量赋值的问题
2017/01/12 Python
PyCharm设置每行最大长度限制的方法
2019/01/16 Python
python时间序列按频率生成日期的方法
2019/05/14 Python
Python操作excel的方法总结(xlrd、xlwt、openpyxl)
2019/09/02 Python
pytorch实现线性拟合方式
2020/01/15 Python
python的sys.path模块路径添加方式
2020/03/09 Python
python能否java成为主流语言吗
2020/06/22 Python
HTML5 b和i标记将被赋予真正的语义
2009/07/16 HTML / CSS
运动与健康自我评价
2015/03/09 职场文书
换届选举主持词
2015/07/03 职场文书
小学生节约用水倡议书
2019/08/12 职场文书