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 相关文章推荐
基于jquery的tab切换 js原理
Apr 01 Javascript
js为空或不是对象问题的快速解决方法
Dec 11 Javascript
node.js中的console.time方法使用说明
Dec 09 Javascript
jQuery中:checkbox选择器用法实例
Jan 03 Javascript
日常收集整理的JavaScript常用函数方法
Dec 10 Javascript
js实现搜索框关键字智能匹配代码
Mar 26 Javascript
jQuery Timelinr实现垂直水平时间轴插件(附源码下载)
Feb 16 Javascript
基于JavaScript实现的希尔排序算法分析
Apr 14 Javascript
layui前段框架日期控件使用方法详解
May 19 Javascript
微信分享调用jssdk实例
Jun 08 Javascript
JavaScript注册时密码强度校验代码
Jun 30 Javascript
微信小程序表单验证功能完整实例
Dec 01 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从数组中删除元素的四种方法实例
2017/05/12 PHP
php框架CodeIgniter主从数据库配置方法分析
2018/05/25 PHP
laravel自定义分页的实现案例offset()和limit()
2019/10/15 PHP
JavaScript学习笔记之获取当前目录的实现代码
2010/12/14 Javascript
JavaScript高级程序设计 阅读笔记(二十一) JavaScript中的XML
2012/09/14 Javascript
javascript执行环境及作用域详解
2016/05/05 Javascript
BootStrap使用popover插件实现鼠标经过显示并保持显示框
2016/06/23 Javascript
使用jQuery.Qrcode插件在客户端动态生成二维码并添加自定义Logo
2016/09/01 Javascript
深入理解JavaScript中的块级作用域、私有变量与模块模式
2016/10/31 Javascript
jquery Easyui Datagrid实现批量操作(编辑,删除,添加)
2017/02/20 Javascript
基于jQuery Easyui实现登陆框界面
2017/07/10 jQuery
从parcel.js打包出错到选择nvm的全部过程
2018/01/23 Javascript
简单的vuex 的使用案例笔记
2018/04/13 Javascript
Next.js项目实战踩坑指南(笔记)
2018/11/29 Javascript
Angular使用ControlValueAccessor创建自定义表单控件
2019/03/08 Javascript
jquery实现简单每周轮换的日历
2020/09/10 jQuery
ES6字符串的扩展实例
2020/12/21 Javascript
[10:21]2018DOTA2国际邀请赛寻真——Winstrike
2018/08/11 DOTA
[03:12]完美世界DOTA2联赛PWL DAY7集锦
2020/11/06 DOTA
使用Python开发windows GUI程序入门实例
2014/10/23 Python
详解Python的Django框架中的模版相关知识
2015/07/15 Python
利用Python爬虫给孩子起个好名字
2017/02/14 Python
解决python3运行selenium下HTMLTestRunner报错的问题
2018/12/27 Python
Python读取xlsx文件的实现方法
2019/07/04 Python
python爬虫 2019中国好声音评论爬取过程解析
2019/08/26 Python
python统计字符串中字母出现次数代码实例
2020/03/02 Python
python基于socket模拟实现ssh远程执行命令
2020/12/05 Python
将HTML5 Canvas的内容保存为图片借助toDataURL实现
2013/05/20 HTML / CSS
澳大利亚票务和娱乐市场领导者:Ticketmaster
2017/03/03 全球购物
旅游饭店管理专业自荐书
2014/06/28 职场文书
社区灵活就业证明
2014/11/03 职场文书
大学生自荐信范文
2015/03/05 职场文书
员工工作表现自我评价
2015/03/06 职场文书
中学教师读书笔记
2015/07/01 职场文书
深入理解Pytorch微调torchvision模型
2021/11/11 Python
JS前端轻量fabric.js系列物体基类
2022/08/05 Javascript