箭头函数
一个速记符号代替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 …;
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
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
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)
}
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:...
}
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"))
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)
})
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"));
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))