相比对ES5 不痛不痒的几个改动,ES6新增了大量的内容。这里先简单罗列一下,后续会一个一个仔细解释。
chrome 已经支持了很多es6的特性,不过被关闭了,你可以在这里打开 chrome://flags/#enable-javascript-harmony。改完之后记得重启浏览器生效。
这可以查看主流浏览器和自己当前浏览器的兼容性 https://kangax.github.io/compat-table/es6/
有些特性即使打开了chrome的配置,依然不支持,比如 class。这个时候可以用 babel 来把 es6 的代码编译成 es5。它支持绝大部分的特性。
而且查看编译后的代码很容易理解这些特性。
地址:https://github.com/babel/grunt-babel
可以用箭头语法来写函数了,很像 lambda 表达式,并且arrow function 会自动绑定this为当前上下文。
目前最新版的 chrome 43 竟然还是不支持,不过最新的火狐已经支持了,可以在火狐下实验。
[1,2,3,4].map(d=>d*d); //单行
//也可以写多行
[1,2,3,4].map(d=>{
console.log(this);
return d*d
});
现在原生支持 class
关键字来声明一个类了,虽然只是一个语法糖,最终还是基于原型继承实现的。但是毕竟可以很方便的实现创建和继承一个类了。
class People {
constructor(name) {
this.name = name;
}
sayName() {
console.log(sayName);
}
}
从上面的类定义可以看出,对象字面量语法做了增强,可以这样写了:
var people = {
name: "Tom",
sayName() { //更方便定义函数
console.log(this.name);
},
[ 'prop_' + (() => 42)() ]: 42 //甚至可以计算属性名
}
还记得在JS中痛苦的拼接html模板么,现在终于有语法支持了,并且用反引号支持多行字符串哦。
var people = {name: "Tom", age: 12};
var html = `
- name: ${people.name}
- age: ${people.age}
`;
这个应该翻译成析构吗。不是很好解释,看下面的代码就很明白。简单的说,就是可以用一个对象来给一个对象的每一个属性赋值(或者数组)。
var [a,b,c]=[1,2,3]; //通过数组给多个变量赋值
var {name, age} = {name: "Tom", age:12} //通过一个对象来给多个变量赋值
//用对象来定义参数
function g({name: x}) {
console.log(x);
}
g({name: 5})
现在可以在函数声明的时候指定一个默认值,还有react中奇怪的三个点号就是这里的延展属性
function say(name="Tom") {
return name;
}
function a(x, ...y) {//延展属性
console.log(x,y)
}
a(1,2,3,4);
可以通过 let 和 const 来声明块级作用于的变量(通过 var 声明的是函数级作用域)。而且 const 声明的是不可变变量。
{
let x=1;
console.log(x);
}
console.log(x);
const y=2;
Iterator 用来实现一个可以用 for 关键字遍历的对象:
let students = {
[Symbol.iterator]() {
let current = 1;
return {
next() {
return {done: current > 100, value: current++};
}
}
}
}
for(s of students) {
console.log(s);
}
//输出 0 - 100
JS终于支持大名顶顶的 yield
了,就是在一个函数内部可以返回多次 return 一个变量。如果用 yield 来实现上面的代码,应该是这样的
let students = {
[Symbol.iterator]: function*() {
for(var i=0;i<=100;i++) {
yield i;
}
}
}
for(var s of students) {
console.log(s);
}
原生支持 unicode,暂时不是很了解这个。
这个必须有!对模块的语法级支持。
export function sum(x, y) {
return x + y;
}
import sum from "math"
sum(1,2);
map 和 set 是一种数据结构,没什么好讲的。 WeakMap 和 WeakSet 用来防止内存泄露,后面有详细讲解。
#map
var m = new Map();
m.set("a", 1);
m.get("a")
#set
var s = new Set();
s.add("a");
s.add("b");
s.add("a"); //不变,因为 a 已经存在了
这里的proxy和 jQuery.proxy 可是两码事,不是用来绑定this的。它和 java 的annotation,python 的 decorator 类似。就是它可以代理一个对象的所有行为,比如你取一个对象的属性,正常是直接取,但是加了 proxy之后,“取”的这个操作会先传个proxy,他来决定到底怎么取。
var target = {};
var handler = {
get: function (receiver, name) {
return `Hello, ${name}!`;
}
};
var p = new Proxy(target, handler);
p.world === 'Hello, world!';
当然他不止可以代理 get,还有 set, has 等一堆操作可以被代理。
Sybmol 用来创建唯一不可变字符串,后面有详细讲解。
现在内置的 Array, Date 和 Element 都可以被继承了
这些是以前就有的类型,不过这次增加了一大推新的API:
"abcd".include("bc");
大家很熟悉的 promise, 现在原生支持了.
估计类似java的反射,可以通过反射机制去操作运行时的对象。
如果不知道什么是尾递归,可以参考这里 http://www.zhihu.com/question/20761771
ES6规定了解释器必须对尾递归进行优化,无论你的尾递归有多少次调用再也不会造成栈溢出了。
function factorial(n, acc = 1) {
'use strict';
if (n <= 1) return acc;
return factorial(n - 1, n * acc);
}
factorial(100000)
上面这个是计算阶乘的,现在在任何浏览器中运行都会造成栈溢出。
后面针对几个重点逐个解析。
这里主要参考这篇文章:
- https://github.com/lukehoban/es6features