ES6特性

箭头函数

一个速记符号代替function(),但是它不会以相同方式绑定this

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

// 花括号申明体
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());

Class类中箭头函数:

class someClass {
    constructor() {
        this.name = "Name"
    }

    testRegular() {
        return function() { return this }

    }

    testArrow() {
        return () => this.name;
    }
}

var obj = new someClass();

console.log(obj.name)
console.log(obj.testRegular()());
console.log(obj.testArrow()());

Classes

我们知道是从“真”语言模仿过来,其实就是一个原型链继承的语法糖。

no-eval
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,

    //  ‘handler: handler’的简写
    handler,

    // 方法
    toString() {

     // Super calls
     return "d " + super.toString();
    },

    // 动态计算属性明
    [ "prop_" + (() => 42)() ]: 42
};

console.log(obj.handler)
console.log(obj.handler())
console.log(obj.toString())
console.log(obj.prop_42)

代码执行 需要chrome支持

字符串模板

var name = "Bob", time = "today";
var multiLine = `This
Line
Spans Multiple
Lines`

console.log(`Hello ${name},how are you ${time}?`)
console.log(multiLine)

解构

// list "matching"
var [a, , b] = [1,2,3];
console.log(a)
console.log(b)

对象也可以解构

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)

箭头函数中的解构

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)

参数位置中的解构使用:

function g({name: x}) {
  return x
}

function m({name}) {
  return name
}

console.log(g({name: 5}))
console.log(m({name: 5}))

未定义解构

var [a] = []
var [b = 1] = []
var c = [];
console.log(a)
console.log(b);
console.log(c);

默认值

function f(x, y=12) {
  return x + y;
}

console.log(f(3))

展开运算符

在函数中

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

在数组中

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

console.log(lyrics)

展开运算符+字面量对象

我们可以在创建对象做一些很酷炫的东西

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)

使用剩余参数操作我们可以无限制的添加参数

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

代替var,比var更加健全的作用域。

{
   var globalVar = "from demo1"
}

{
   let globalLet = "from demo2";
}

console.log(globalVar)
console.log(globalLet)

以后不会默认挂载在window变量下:

et me = "go";  // globally scoped
var i = "able"; // globally scoped

console.log(window.me); 
console.log(window.i);

output:
window.me -> undefined window.i -> able
如果使用let不可以重复声明变量了

let me = "foo";
let me = "bar"; 
console.log(me);

output:
SyntaxError: Identifier 'me' has already been declared

var me = "foo";
var me = "bar"; 
console.log(me)

output:
me -> bar

Const

const是常量

const a ="b"
a="a"

output:
TypeError: Assignment to constant variable.
这里需要注意的是const对象是可以变化的

const a = {a:'a'}
a.a = "b"
console.log(a)

output:
a ->{"a":"b"}

For..of

迭代新类型,一个替代 for .. in 返回值将由keys替换values(for..in 遍历输入值为keys,而for..of是values)

let list = [4, 5, 6];

console.log(list)

for (let i in list) {
   console.log(i);
}

output:

list -> [4,5,6]
i -> 0
i -> 1
i -> 2

VS

let list = [4, 5, 6];

console.log(list)


for (let i of list) {
   console.log(i); 
}

output:

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

output:

"start" -> start
n -> 1
n -> 2
n -> 3
n -> 4
n -> 5
n -> 6
n -> 7
n -> 8
n -> 9
n -> 10

使用Typescript interfaces 我们看看他们的样子

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

Generators(生成器)

生成器创建一个迭代器(iterators),比迭代器(iterators)更加动态,他不会跟踪记录状态,不支持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);
}

output:

"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
一个 yield*相关例子:

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

output:

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

output:

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

Sets作为一个数学的配对物,所有的子项都是唯一的,就类似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)
}

output

set.size -> undefined
set.has({a:"Tomato"}) -> false
set.has(item) -> true
TypeError: undefined is not a function

WeakSet

Map

Maps,顾名思义数据字典

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

output

map.get("Potato") -> 12
item -> ["Potato",12]
item -> ["Tomato",34]

key值可以使用对象,但是非同一引用不能获取值

var map = new Map();
var key = {a: "a"}
map.set(key, 12);


console.log(map.get(key))
console.log(map.get({a: "a"}))

output:

map.get(key) -> 12
map.get({a: "a"}) -> undefined

weakMap

所有key值都为对象,且key值对象只能保持弱引用。

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

weakMap

Proxies

代理可以用来改变对象的行为,它允许我们定义一个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);

The following traps are available:

no-eval
var handler =
{
  get:...,
  set:...,
  has:...,
  deleteProperty:...,
  apply:...,
  construct:...,
  getOwnPropertyDescriptor:...,
  defineProperty:...,
  getPrototypeOf:...,
  setPrototypeOf:...,
  enumerate:...,
  ownKeys:...,
  preventExtensions:...,
  isExtensible:...
}

Proxies

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"))

More info

Inheritable Built-ins(内置对象可以继承)

现在我们可以继承原生的class

class CustomArray extends Array {

}

var a = new CustomArray();

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

如果没有使用Proxies的Aarry使用继承是不可能改变原生getter

New Library(新库)

各种新的方法和常量

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

Documentation: Number, Math, Array.from, Array.of, Array.prototype.copyWithin, Object.assign

二进制和八进制

字面二进制和八进制数字

console.log(0b11111)
console.log(0o2342)

console.log(0xff); // also in es5

Promises

Need a quick always resolved promise?

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

Quick Promise

Need a quick always resolved promise?

var p1 = Promise.resolve("1")
var p2 = Promise.reject("2")

Promise.race([p1, p2]).then((res) => {
   console.log(res)
})

Fail fast

If a promise fails, all and race will reject as well.

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

More Info

Reflect

New type of meta programming with new API for existing and also a few new methods.

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

More Info

Tail Call Optimization

ES6 should fix ensure tail calls do not generate stack overflow. (Not all implementations work).

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))
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 157,012评论 4 359
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,589评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 106,819评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,652评论 0 202
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 51,954评论 3 285
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,381评论 1 210
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,687评论 2 310
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,404评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,082评论 1 238
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,355评论 2 241
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,880评论 1 255
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,249评论 2 250
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,864评论 3 232
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,007评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,760评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,394评论 2 269
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,281评论 2 259

推荐阅读更多精彩内容

  • ES6特性归纳 ES的全称是ECMAScript,它是JavaScript的规格,JS是ES的一种实现。ES还有J...
    FWHeart阅读 544评论 0 4
  • ES6新特性 let关键字 控制作用域在块级作用域下的定义关键字,并且不允许重复声明,举例: 注:在没有let关键...
    dawsonenjoy阅读 855评论 0 1
  • 1 let const 1.1 let let 声明的变量是在其块级作用域起作用,与 var 相似。二者之间最主要...
    林ze宏阅读 562评论 1 1
  • 为了保证可读性,本文采用意译而非直译,并且对源代码进行了大量修改。另外,本文版权归原作者所有,翻译仅用于学习。 E...
    强哥科技兴阅读 209评论 0 0
  • 下面是10个ES6最佳特性,排名不分先后: 1.函数参数默认值 2.模板字符串 3.多行字符串 4.解构赋值 5....
    痛心凉阅读 233评论 0 0