目录
前言- ECMAScript 6简介
- let 和 const 命令
- 变量的解构赋值
- 字符串的扩展
- 字符串的新增方法
- 正则的扩展
- 数值的扩展
- 函数的扩展
- 数组的扩展
- 对象的扩展
- 对象的新增方法
运算符的扩展- Symbol
- Set 和 Map 数据结构
- Proxy
- Reflect
- Promise 对象
- Iterator 和 for...of 循环
- Generator 函数的语法
- Generator 函数的异步应用
- async 函数
- Class 的基本语法
- Class 的继承
- Module 的语法
- Module 的加载实现
- 编程风格
- 读懂规格
- 异步遍历器
- ArrayBuffer
- 最新提案
- Decorator
基础语法
Object
Object.is()
Object.is(+0, -0) // false
Object.is(NaN, NaN) // true
Object.defineProperty(Object, 'is', {
value: function(x, y) {
if (x === y) {
// 针对+0 不等于 -0的情况
return x !== 0 || 1 / x === 1 / y;
}
// 针对NaN的情况
return x !== x && y !== y;
},
configurable: true,
enumerable: false,
writable: true
});
Object.assign()
???
Object.getOwnPropertyDescriptors()
运算符的扩展
// 指数运算符,右结合
a ** b
a **= 2
// 可选链
?.
// Null 判断
??
// 逻辑赋值
编程风格
let 取代 var 全局不应该设置变量,而应该用 const 设置常量 所有的函数应该设置为常量 使用严格模式 静态字符串使用单引号或反引号 动态字符串使用双引号 使用解构赋值,包括函数参数、返回值 多行定义的对象最后一个成员以逗号结尾 尽量不修添加对象属性,如果修改,使用Object.assign()
基础
- 变量提升 & 暂时性死区
- let 和 const 的全局变量不再属于顶层对象的属性
字符串扩展
codePointAt() // charCodeAt()
String.fromCodePoint() // fromCharCode()
formCodePoint方法定义在String对象上,codePointAt方法定义在字符串的实例对象上。
可以使用for…of
at() // charAt()
normalize() // Unicode正规化,统一字符的不同表示方法
includes(), startsWith(), endsWith()
repeat()
padStart(), padEnd()
String.raw
// 模板字符串1
let str = 'return ' + '`Hello ${name}`';
let func = new Function('name', str);
func('Jack');
// 模板字符串2
let str = '(name) => `Hello ${name}`';
let func = eval.call(null, str);
func('Jack');
正则的扩展
修饰符u,y, ???
数值的扩展
二进制 0b 八进制 0o Number.isFinite() Number.isNaN() Number.parseInt() Number.parseFloat() Number.isInteger() Number.EPSILON Number.MAX_SAFE_INTEGER Number.MIN_SAFE_INTEGER Number.isSageInteger() Math 新增17个方法 Math.trunc() 去掉小数 Math.sign() 判断正负 Math.cbrt() 立方根 Math.clz32() Math.imul() Math.fround() Math.hypot() Math.expm1()、Math.log1p()、Math.log10()、Math.log2() Math.sinh(x)、Math.cosh(x)、Math.tanh(x)、Math.asinh(x)、Math.acosh(x)、Math.atanh(x) 、=
数组的扩展
扩展运算符
...[]
复制、合并数组,替代ES5的arr.concat()
任何定义了遍历器(Iterator)接口的对象(参阅 Iterator 一章),都可以用扩展运算符转为真正的数组。
Array.from()
函数的扩展
允许默认值 赋值与解构赋值结合 ???
rest 参数
- 通过声明 function funcName(...args){} 得到 args 是一个数组。
- rest 参数必须是最后一个参数。
- 函数的 length 属性不包括 rest 参数。
对比arguments[]思考:
const sortNumbers = () => Array.prototype.slice.call(arguments).sort()
const sortNumbers = (...numbers) => numbers.sort()
// arguments 不能调用数组的方法
箭头函数
var f = v => v
// 等同于
var f = function(v) {
return v;
}
var f = () => 5
var f = (a, b) => a + b
var f = id => ({ id: id }) // 返回对象需要加括号
// 只有一行且不需要返回值
var f = () => void doesNotReturn();
- 函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象。
- 不可以当作构造函数,也就是说,不可以使用new命令,否则会抛出一个错误。
- 不可以使用arguments对象,该对象在函数体内不存在。如果要用,可以用 rest 参数代替。
- 不可以使用yield命令,因此箭头函数不能用作 Generator 函数。
箭头函数可以用于回调,不会改变this指向。
除了this,以下三个变量在箭头函数之中也是不存在的,指向外层函数的对应变量:arguments、super、new.target。
Symbol
注意,Symbol函数前不能使用new命令,否则会报错。这是因为生成的 Symbol 是一个原始类型的值,不是对象。也就是说,由于 Symbol 值不是对象,所以不能添加属性。基本上,它是一种类似于字符串的数据类型。
Promise
var a = 0;
const p1 = new Promise(function (resolve, reject) {
setTimeout(() => {
console.log('p1')
resolve('0')
}, 10000)
})
// for(var i=0;i<999999999;i++) {
// a+=i;
// }
const p2 = new Promise(function (resolve, reject) {
setTimeout(() => {
console.log('p2')
resolve(p1)
}, 10000)
})
// for(var i=0;i<999999999;i++) {
// a+=i;
// }
const p3 = new Promise(function (resolve, reject) {
setTimeout(() => {
console.log('p3')
resolve(p2)
}, 20000)
})
p3.then(e => console.log(e))
Promise.all()方法的参数可以不是数组,但必须具有 Iterator 接口,且返回的每个成员都是 Promise 实例。
Class
class Point{
constructor(x,y){
this.x = x;
this.y = y;
}
toString(){
return 'test';
}
}
typeof Point // 'function'
Point === Point.prototype.constructor // true
Object.assign(Point.prototype, {
toValue(){},
toString(){}
})
类的方法名可以是表达式
Module
- 模块简介 ✓
CommonJS
运行时加载,无法在编译时做“静态优化”
ES6 模块不是对象,而是通过export命令显式指定输出的代码,再通过import命令输入。
CommonJS 模块是对象。
“编译时加载” = 静态加载 -> 静态分析成为可能
这样的设计,固然有利于编译器提高效率,但也导致无法在运行时加载模块。
模块整体加载所在的那个对象(上例是circle),应该是可以静态分析的,所以不允许运行时改变。下面的写法都是不允许的。
import * as circle from './circle';
// 下面两行都是不允许的
circle.foo = 'hello';
circle.area = function () {};
export default
export
export var foo = 'bar';
export var baz = 'qux';
// 也可以
export { foo, bar };
// 可以使用 as 重命名变量
export {
foo as a,
bar as b,
bar as c
};
// 错误1
export 1;
// 错误2
var m = 1;
export m;
// 正确
export var m = 1;
// 正确
var m = 1;
export { m };
// 正确
var n = 1;
export {n as m};
// 正确
export default 1;
export default
使用export default之后,在import的时候可以指定任意名字。不再需要大括号。相当于:
// modules.js
function foo() {}
export {foo as default};
// app.js
import {default as bar} from 'modules';
// 正确
export var a = 1;
// 正确
var a = 1;
export default a;
// 错误
export default var a = 1;
import
import 的变量是只读的。
import { foo, bar } from 'foobar'
import { foo as a} from 'foobar'
import 是编译阶段执行的
静态执行,不能使用表达式。
import { foo } from 'my_module';
import { bar } from 'my_module';
// 等同于
import { foo, bar } from 'my_module';
import _, { each, forEach } from 'lodash';