本文参考阮一峰老师的《 ECMAScript 6 入门》
es6的内容大概分为:变量声明、解构赋值、字符串扩展、数值扩展、对象扩展、数组扩展、函数扩展、正则扩展、Symbol、Set、Map、Proxy、Reflect、Class、Module、Iterator、异步编程(Promise、Generator、Async)
变量声明
const: 声明常量,声明时就要立马赋值,赋值后不可更改,声明对象时只是不可更改变量的引用地址可以更改对象的属性
let: 声明变量,声明但未赋值时变量为undefined
作用域分为全局作用域、函数作用域(function(){})、块作用域({})
const、let没有变量提升,所以存在暂时性死区(js引擎没有读到变量声明时就使用变量)未定义就使用会报错,有块级作用域
解构赋值
匹配模式:只要等号两边的模式相同,左边的变量就会被赋予对应的值,解构不成功,变量的值就等于undefined。还有一种叫不完全解构,等号左边的模式,只匹配一部分的等号右边的数组。等号右边的不是数组则会报错。
匹配模式
const [a, b, c, d, e] = 'hello';
a // "h"
b // "e"
c // "l"
d // "l"
e // "o"
let [foo, [[bar], baz]] = [1, [[2], 3]];
foo // 1
bar // 2
baz // 3
let [ , , third] = ["foo", "bar", "baz"];
third // "baz"
let [x, , y] = [1, 2, 3];
x // 1
y // 3
不完全解构
let [x, y] = [1, 2, 3];
x // 1
y // 2
let [a, [b], d] = [1, [2, 3], 4];
a // 1
b // 2
d // 4
Set也可以使用数组解构赋值
let [x, y, z] = new Set(['a', 'b', 'c']);
x // "a"
解构赋值允许默认值,但是只有当一个数组成员或对象的属性值严格等于undefined,默认值才会生效。默认值可以使用变量,但变量必须是已经声明
let [x = 1] = [undefined];
x // 1
let [x = 1] = [null];
x // null
var {x = 3} = {x: undefined};
x // 3
var {x = 3} = {x: null};
x // null
对象也可以解构,变量必须与属性同名,才能取到正确的值,如果解构失败,变量的值等于undefined。
let { bar, foo } = { foo: 'aaa', bar: 'bbb' };
foo // "aaa"
bar // "bbb"
let { baz } = { foo: 'aaa', bar: 'bbb' };
baz // undefined
解构赋值的规则是,只要等号右边的值不是对象或数组,就先将其转为对象。由于undefined和null无法转为对象,所以对它们进行解构赋值,都会报错。
字符串扩展
字符串遍历:可通过for-of遍历字符串
模板字符串:用反引号(`)标识。它可以当作普通字符串使用,也可以用来定义多行字符串,或者在字符串中嵌入变量
repeat():把字符串重复n次,返回新字符串
matchAll() :返回正则表达式在字符串的所有匹配
includes() :是否存在指定字符串
startsWith() :字符串头部是否存在指定字符串
endsWith() :字符串尾部是否存在指定字符串
padStart(a,b): 头部补全,第一个参数是字符串补全生效的最大长度,第二个参数是用来补全的字符串。
padEnd(a,b): 尾部补全,第一个参数是字符串补全生效的最大长度,第二个参数是用来补全的字符串。
trim(): 消除空格; trimStart():消除字符串头部空格; trimEnd():消除字符串尾部空格
replaceAll(): 替换 'aabbcc'.replaceAll('b', '_') //aa__cc
数值扩展
Number.isFinite() 检查数值是否为有限
Number.isNaN() 检查值是否为NaN
Number.parseInt() 整数
Number.parseFloat() 浮点数
Number.isInteger() 判断数值是否为整数
Number.MIN_SAFE_INTEGER:最小安全数值(-2^53)
Number.MAX_SAFE_INTEGER:最大安全数值(2^53)
Math.trunc() 去除一个数的小数部分返回整数
Math.sign():返回数值类型,参数是非数值,会自动转为数值(正数+1、负数-1、零0、其他值NaN)
对象扩展
for...in循环遍历对象自身的和继承的可枚举属性(不含 Symbol 属性)
Object.keys返回一个数组,包括对象自身的(不含继承的)所有可枚举属性(不含 Symbol 属性)的键名。
Object.getOwnPropertyNames返回一个数组,包含对象自身的所有属性(不含 Symbol 属性,但是包括不可枚举属性)的键名。
Object.getOwnPropertySymbols返回一个数组,包含对象自身的所有 Symbol 属性的键名。
Reflect.ownKeys返回一个数组,包含对象自身的(不含继承的)所有键名,不管键名是 Symbol 或字符串,也不管是否可枚举。
super关键字指向当前对象的原型对象
Object.is() 判断两个值是否严格相等
Object.assign(target,source1,source2) 将源对象所有可枚举属性赋值到目标对象上,若有同名属性则会发生覆盖
Object.getPrototypeOf() 返回对象的原型对象 Object.setPrototypeOf() 设置对象的原因对象
Object.values() 返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历属性的键值。
Object.entries() 返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历属性的键值对数组。
数组扩展
扩展运算符(...):将一个数组转为用逗号分隔的参数序列
Array.from() 将类数组对象和可遍历对象转化为真正的数组
Array.of() 将一组值转化为数组
copyWithin() 把指定位置的成员复制到其他位置,返回原数组
find():返回第一个符合条件的数组成员
findIndex():返回第一个符合条件的成员索引值
fill() 根据指定值填充整个数组,返回原数组
keys():返回以键名为遍历器的对象
values():返回以属性值为遍历器的对象
entries():返回以键名和属性值为遍历器的对象
Array.prototype.includes() 数组是否包含给定的值
数组空位: es6将数组空位转换为undefined
函数扩展
参数可以设置默认值
函数的length属性将返回没有指定默认值的参数个数,函数的name属性将返回函数名
箭头函数()=>{} 箭头函数没有自己的this对象、不能当构造函数不可以使用new命令
尾调用: 指某个函数的最后一步是调用另一个函数。
Symbol
symbol是数据类型之一,用来表示独一无二的值。Symbol()函数前不能使用new命令,否则会报错。
声明: let s1 = Symbol('foo'); 相同参数的Symbol函数的返回值是不相等的
// 没有参数的情况
let s1 = Symbol();
let s2 = Symbol();
s1 === s2 // false
// 有参数的情况
let s1 = Symbol('foo');
let s2 = Symbol('foo');
s1 === s2 // false
Symbol 值不能与其他类型的值进行运算,会报错。Symbol 值可以显式转为字符串或布尔值。
通过Symbol.for()产生的相同参数的symbol值相等
let s1 = Symbol.for('foo');
let s2 = Symbol.for('foo');
s1 === s2 // true
Symbol值作为对象属性名时,只能用方括号运算符([])读取,不能用点运算符(.)读取
Set和Map
Set:类似于数组的数据结构,成员值都是唯一且没有重复的值
声明:const s = new Set()
去除数组中重复的成员
[...new Set(array)]
添加相同的对象时,会认为是不同的对象;添加多个NaN时,只会存在一个NaN
方法
- add() :添加值,返回实例
- delete() :删除值,返回布尔
- has() :检查值,返回布尔
- clear() :清除所有成员
- keys() :返回以属性值为遍历器的对象
- values() :返回以属性值为遍历器的对象
- entries() :返回以属性值和属性值为遍历器的对象
- forEach() :使用回调函数遍历每个成员
Map: 类似于对象的数据结构,成员键是任何类型的值
声明:const m = new Map()
size属性返回 Map 结构的成员总数
方法
- get() :返回键值
- set() :添加键值对,返回实例
- delete() :删除键值对,返回布尔
- has() :检查键值对,返回布尔
- clear() :清除所有成员
- keys() :返回以键为遍历器的对象
- values() :返回以值为遍历器的对象
- entries() :返回以键和值为遍历器的对象
- forEach() :使用回调函数遍历每个成员
Proxy
proxy可以理解为在目标对象之前架设一层“拦截”,外界对该对象的访问,都必须先通过这层拦截,因此提供了一种机制,可以对外界的访问进行过滤和改写。
var proxy = new Proxy(target, handler);//`new Proxy()`表示生成一个`Proxy`实例,`target`参数表示所要拦截的目标对象,`handler`参数也是一个对象,用来定制拦截行为。
class
类本身指向构造函数,所有方法定义在prototype上,可看作构造函数的另一种写法(Class === Class.prototype.constructor)
-
方法和关键字
- constructor() :构造函数,
new命令生成实例时自动调用,constructor()方法是类的默认方法,通过new命令生成对象实例时,自动调用该方法。一个类必须有constructor()方法,如果没有显式定义,一个空的constructor()方法会被默认添加。 - extends:继承父类
- super:新建父类的
this - static:定义静态属性方法,不会被实例继承,只能通过类来调用
- get:取值函数,拦截属性的取值行为
- set:存值函数,拦截属性的存值行为
- constructor() :构造函数,
class Point {
constructor(x, y) {
super()
this.x = x;
this.y = y;
}
get prop() {
return 'getter';
}
set prop(value) {
console.log('setter: '+value);
}
toString() {
return '(' + this.x + ', ' + this.y + ')';
}
}
Promise
Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果
-
状态
- 进行中:
pending - 已成功:
resolved - 已失败:
rejected
- 进行中:
-
特点
- 对象的状态不受外界影响
- 一旦状态改变就不会再变,任何时候都可得到这个结果
`Promise`构造函数接受一个函数作为参数,该函数的两个参数分别是`resolve`和`reject`函数。
resolve是将promise状态从未完成变为`成功`,reject是将promise状态从未完成变为`失败`
const promise = new Promise(function(resolve, reject) {
// ... some code
if (/* 异步操作成功 */){
resolve(value);
} else {
reject(error);
}
});
`Promise`实例生成以后,可以用`then`方法分别指定`resolved`状态和`rejected`状态的回调函数。
`then`方法可以接受两个回调函数作为参数。第一个回调函数是`Promise`对象的状态变为`resolved`时调用,第二个回调函数是`Promise`对象的状态变为`rejected`时调用。
`catch`方法是发生错误时的回调函数
promise.then(function(value) {
// success
}, function(error) {
// failure
}).catch(err=>{
//console.log(err)
});
Promise.all() :接受一个数组作为参数,当数组中的promise实例状态全变成fulfilled,最终状态才会变成fulfilled;其中一个实例状态变成rejected,最终状态就会变成rejected
const p1 = new Promise((resolve, reject) => {
resolve('hello');
})
.then(result => result)
.catch(e => e);
const p2 = new Promise((resolve, reject) => {
throw new Error('报错了');
})
.then(result => result)
.catch(e => e);
Promise.all([p1, p2])
.then(result => console.log(result))
.catch(e => console.log(e));
// ["hello", Error: 报错了]