ES6是ECMA为JavaScript制定的第6个标准版本
ES6更新的内容主要分为以下几点
- 表达式:声明、解构赋值
- 内置对象:字符串拓展、数值类型拓展、对象拓展、数组拓展、函数拓展、正则拓展、Set、Map、Proxy、Reflect
- 语句与运算:Class、Module、Iterator
- 异步编程:Promise、Async、Generator
const声明常量,let声明变量
作用域:全局、函数、块级
作用范围:var命令在全局代码执行,const和let只能在代码块中执行
重点:
字符串 const [a,b,c,d,e] = "hello"
数组 const {toString: s } = 123
布尔 const {toString: s } = true
数组
const [x,y] = [1,2]
const [a='a',b='b'] = ["111","222"]
对象解构
const {p,q} = {p:1,q:false}; //基本赋值 p=1 q=false
var a,b;
({a,b} = {a:1, b:2}); //对象字面量无声明解构赋值时是必须的。
const { x, y: z } = { x: 1, y: 2 } //给新的变量名赋值 {x:1,z:2}
```
函数参数结构
应用场景:交换变量值、返回函数多个值、提取JSON数据
重点:
字符串遍历:可通过for-of遍历字符串
模板字符串 可以换行,但是所有的空格和换行会被保留。
const h = 'hello'
` ${ h } word `
Unicode表示法 //大括号包含表示Unicode字符(\u{0xXX}或\u{0XXX})
字符串方法拓展:
String.raw() //返回把字符串所有变量替换且对斜杠进行转义的结果
String.fromCodePoint() //返回码点对应字符
codePointAt() //返回字符对应码点(String.fromCodePoint()的逆操作)
normalize() //把字符的不同表示方法统一为同样形式,返回新字符串(Unicode正规化)
repeat() //把字符串重复n次,返回新字符串
matchAll() //返回正则表达式在字符串的所有匹配
includes() //是否存在指定字符串
startsWith() //是否存在字符串头部指定字符串
endsWith() //是否存在字符串尾部指定字符串
数值方法拓展
//二进制表示法0b或0B开头表示二进制(0bXX或0BXX)
//八进制表示法0o或0O开头表示二进制(0oXX或0OXX)
Number.EPSILON//数值最小精度
Number.MIN_SAFE_INTEGER//最小安全数值(-2^53)
Number.MAX_SAFE_INTEGER//最大安全数值(2^53)
Number.parseInt()//返回转换值的整数部分
Number.parseFloat()//返回转换值的浮点数部分
Number.isFinite()//是否为有限数值
Number.isNaN()//是否为NaN
Number.isInteger()//是否为整数
Number.isSafeInteger()://否在数值安全范围内
//以及各种Math方法
{prop, method(){}}
obj.foo = true; // 方法一 直接用标识符作属性名
obj['a' + 'bc'] = 123; // 方法二 表达式做属性名
// ES6 允许字面量定义对象时,用方法二(表达式)作为对象的属性名
//,即把表达式放在方括号内。
let lastWord = 'last word';
const a = {
'first word': 'hello',
[lastWord]: 'world'
};
a['first word'] // "hello"
a[lastWord] // "world"
a['last word'] // "world"
Object.getOwnPropertyDescriptor 中enumerable为true则为可枚举,反之则不行
Object.is()//对比两值是否相等
Object.assign()//合并对象(浅拷贝),返回原对象
Object.getPrototypeOf()//返回对象的原型对象
Object.setPrototypeOf()//设置对象的原型对象
\_\_proto\_\_//返回或设置对象的原型对象
for-in//遍历对象自身可继承可枚举属性
Object.keys()//返回对象自身可枚举属性键组成的数组
Object.getOwnPropertyNames()//返回对象自身非Symbol属性键组成的数组
Object.getOwnPropertySymbols()://返回对象自身Symbol属性键组成的数组
Reflect.ownKeys()//返回对象自身全部属性键组成的数组
规则:
...
,内部使用for…of循环。function add(...values) {
let sum = 0;
for (var val of values) {
sum += val;
}
return sum;
}
add(1, 2, 3) // 6
Array.from() //转换具有Iterator接口的数据结构为真正数组,返回新数组
Array.of() //转换一组值为真正数组,返回新数组
copyWithin(): //指定位置的成员复制到其他位置,返回原数组
find() //返回第一个符合条件的成员
findIndex() //返回第一个符合条件的成员索引值
fill() //根据指定值填充整个数组,返回原数组
keys() //返回以索引值为遍历器的对象
values() //返回以属性值为遍历器的对象
entries() //返回以索引值和属性值为遍历器的对象
//ES6明确将数组空位转为undefined(空位处理规不一,建议避免出现)
``
重点:
使用keys()、values()、entries()
返回的遍历器对象,可用for-of
自动遍历或next()
手动遍历
参数默认值:为函数参数指定默认值 Func(x=1,y=2){}
指定某个参数不得省略,否则抛出err:Func(x=throwMissing()){}
将参数默认值为undefined,表面此参数可省略Func(undefined,1){}
rest/spread 参数,也就是(…),返回函数的多余参数,以数组形式中存在
name 属性:返回函数的函数名
箭头函数
尾调用优化:在某个函数的最后异步调用另一个函数 return f(x)
箭头函数重点:
定义:独一无二的值
声明:const set = Symbol(‘123’),参数为字符串,可选
方法:
Symbol()//创建以参数作为描述的Symbol值(不登记在全局环境)
Symbol.for()//创建以参数作为描述的Symbol值,如存在此参数则返回原有的Symbol值(先搜索后创建,登记在全局环境)
Symbol.keyFor()//返回已登记的Symbol值的描述(只能返回Symbol.for()的key)
Object.getOwnPropertySymbols()//返回对象中所有用作属性名的Symbol值的数组
注意:
Symbol
函数前不能使用new
命令,否则会报错。这是因为生成的 Symbol 是一个原始类型的值,不是对象。也就是说,由于 Symbol 值不是对象,所以不能添加属性。基本上,它是一种类似于字符串的数据类型。Symbol
函数的参数只是表示对当前 Symbol
值的描述,因此相同参数的Symbol
函数的返回值是不相等的。Symbol
值作为对象属性名时间,不能用点运算符重点:
定义:类似于数组的数据结构,成员值都是唯一且没有重复的值。
Set本身是一个构造函数,用来生成 Set 数据结构。
入参:具有Iterator
接口的数据结构(可循环、遍历)
属性:
constructor
构造函数,返回Set
size
返回实例成员总数
方法:
add() //添加值,返回实例,可以采用链式写法
delete() //删除值,返回布尔
has() //检查值,返回布尔
clear() //清除所有成员
keys() //返回键名的遍历器,又因为Set容器没有键名只有键值(或者说键名和键值是同一个值),所以还是返回键值
values() //返回以键值为遍历器的对象
entries() //返回以属性值和属性值为遍历器的对象
forEach() //使用回调函数遍历每个成员
应用:
[...new Set(str)].join('')
[...new Set([arr])]
或者 Array.from(new Set(arr))
const a = new Set(arr1)、const b = new Set(arr2)
new Set([...a, ...b])
new Set([...a].filter(v => b.has(v)))
new Set([...a].filter(v => !b.has(v)))
// 方法一
let set = new Set([1, 2, 3]);
set = new Set([...set].map(val => val * 2));
// set的值是2, 4, 6
// 方法二
let set = new Set([1, 2, 3]);
set = new Set(Array.from(set, val => val * 2));
// set的值是2, 4, 6
重点:
WeakSet 结构与 Set 类似,也是不重复的值的集合。但是,它与 Set 有两个区别。
首先,WeakSet 的成员只能是对象,而不能是其他类型的值。
其次,WeakSet 中的对象都是弱引用,即垃圾回收机制不考虑 WeakSet 对该对象的引用,
WeakSet 的成员是不适合引用的,因为它会随时消失。另外,由于 WeakSet 内部有多少个成员,取决于垃圾回收机制有没有运行,运行前后很可能成员个数是不一样的,而垃圾回收机制何时运行是不可预测的,
JS的对象(Object),本质上是键值对的集合(Hash 结构),但是传统上只能用字符串当作键。这给它的使用带来了很大的限制。
为了解决这个问题,ES6 提供了 Map 数据结构。它类似于对象,也是键值对的集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。
定义:类似于对象的数据结构,成员键是任何类型的值
入参:具有Iterator接口且每个成员都是一个双元素数组的数据结构(Array、Set、Map…)
属性:
方法:
get() //返回键值对
set() //添加键值对,返回实例,可以采用链式写法
delete() //删除键值对,返回布尔
has() //检查键值对,返回布尔
clear() //清除所有成员
keys() //返回以键为遍历器的对象
values() //返回以值为遍历器的对象
entries() //返回以键和值为遍历器的对象
forEach() //使用回调函数遍历每个成员
样例:
let map = new Map();
map.set(-0, 123);
map.get(+0) // 123
map.set(true, 1);
map.set('true', 2);
map.get(true) // 1
map.set(undefined, 3);
map.set(null, 4);
map.get(undefined) // 3
map.set(NaN, 123);
map.get(NaN) // 123
重点:
字符串-值
对应,map提供值-值
对象WeakMap结构与Map结构类似,也是用于生成键值对的集合。
区别:
基本上,如果你要往对象上添加数据,又不想干扰垃圾回收机制,就可以使用 WeakMap。一个典型应用场景是,在网页的 DOM 元素上添加数据,就可以使用WeakMap结构。当该 DOM 元素被清除,其所对应的WeakMap记录就会自动被移除。
总之,WeakMap的专用场合就是,它的键所对应的对象,可能会在将来消失。WeakMap结构有助于防止内存泄漏。
重点:
WeakSet 和 WeakMap 是基于弱引用的数据结构,ES6 更进一步,提供了 WeakRef 对象,用于直接创建对象的弱引用。
let target = {};
let wr = new WeakRef(target);
上面示例中,target是原始对象,构造函数WeakRef()创建了一个基于target的新对象wr。这里,wr就是一个 WeakRef 的实例,属于对target的弱引用,垃圾回收机制不会计入这个引用,也就是说,wr的引用不会妨碍原始对象target被垃圾回收机制清除。
WeakRef 实例对象有一个deref()方法,如果原始对象存在,该方法返回原始对象;如果原始对象已经被垃圾回收机制清除,该方法返回undefined。
Proxy 用于修改某些操作的默认行为,等同于在语言层面做出修改,相当于重写某部分操作功能
声明:const proxy = new Proxy(target, handler)
入参:
样例1:
var obj = new Proxy({}, {
get: function (target, propKey, receiver) {
console.log(`getting ${propKey}!`);
return Reflect.get(target, propKey, receiver);
},
set: function (target, propKey, value, receiver) {
console.log(`setting ${propKey}!`);
return Reflect.set(target, propKey, value, receiver);
}
});
obj.count = 1
// setting count!
++obj.count
// getting count!
// setting count!
// 2
上面代码说明,Proxy 实际上重载(overload)了点运算符,即用自己的定义覆盖了语言的原始定义
样例2:
var proxy = new Proxy({}, {
get: function(target, propKey) {
return 35;
}
});
proxy.time // 35
proxy.name // 35
proxy.title // 35
上面代码中,配置对象有一个get方法,用来拦截对目标对象属性的访问请求。get方法的两个参数分别是目标对象和所要访问的属性。可以看到,由于拦截函数总是返回35,所以访问任何属性都得到35。
Proxy 实例也可以作为其他对象的原型对象。
var proxy = new Proxy({}, {
get: function(target, propKey) {
return 35;
}
});
let obj = Object.create(proxy);
obj.time // 35
上面代码中,proxy对象是obj对象的原型,obj对象本身并没有time属性,所以根据原型链,会在proxy对象上读取该属性,导致被拦截。
拦截方法:
get(target, propKey, receiver) //拦截对象属性的读取,比如proxy.foo和proxy['foo']。
set(target, propKey, value, receiver) //拦截对象属性的设置,比如proxy.foo = v或proxy['foo'] = v,返回一个布尔值。
has(target, propKey) //拦截propKey in proxy的操作,返回一个布尔值。
deleteProperty(target, propKey) //拦截delete proxy[propKey]的操作,返回一个布尔值。
ownKeys(target) //拦截Object.getOwnPropertyNames(proxy)、Object.getOwnPropertySymbols(proxy)、Object.keys(proxy)、for...in循环,返回一个数组。该方法返回目标对象所有自身的属性的属性名,而Object.keys()的返回结果仅包括目标对象自身的可遍历属性。
getOwnPropertyDescriptor(target, propKey) //拦截Object.getOwnPropertyDescriptor(proxy, propKey)返回属性的描述对象。
defineProperty(target, propKey, propDesc) //拦截Object.defineProperty(proxy, propKey, propDesc)、Object.defineProperties(proxy, propDescs),返回一个布尔值。
preventExtensions(target) //拦截Object.preventExtensions(proxy),返回一个布尔值。
getPrototypeOf(target) //拦截Object.getPrototypeOf(proxy),返回一个对象。
isExtensible(target) //拦截Object.isExtensible(proxy),返回一个布尔值。
setPrototypeOf(target, proto) //拦截Object.setPrototypeOf(proxy, proto),返回一个布尔值。如果目标对象是函数,那么还有两种额外操作可以拦截。
apply(target, object, args) //拦截 Proxy 实例作为函数调用的操作,比如proxy(...args)、proxy.call(object, ...args)、proxy.apply(...)。
construct(target, args) //拦截 Proxy 实例作为构造函数调用的操作,比如new proxy(...args)。
应用场景:
Proxy.revocable() //不允许直接访问对象,必须通过代理访问,一旦访问结束就收回代理权不允许再次访问
get() //读取未知属性报错、读取数组负数索引的值、封装链式操作、生成DOM嵌套节点
set() //数据绑定(Vue数据绑定实现原理)、确保属性值设置符合要求、防止内部属性被外部读写
has() //隐藏内部属性不被发现、排除不符合属性条件的对象
deleteProperty() //保护内部属性不被删除
defineProperty() //阻止属性被外部定义
ownKeys() //保护内部属性不被遍历
重点:
Reflect始终保持Object方法的默认行为,未来的新方法也会放在Reflect对象上
Reflect对象与Proxy对象一样,也是 ES6 为了操作对象而提供的新 API。
静态方法:
Reflect.apply(target, thisArg, args) //绑定this后执行指定函数
Reflect.construct(target, args) //等同于new target(...args),这提供了一种不使用new,来调用构造函数的方法。
Reflect.get(target, name, receiver) //查找并返回target对象的name属性,如果没有该属性,则返回undefined。
Reflect.set(target, name, value, receiver) //设置target对象的name属性等于value。
Reflect.defineProperty(target, name, desc) //该方法可以在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回这个对象。
Reflect.deleteProperty(target, name) //等同于delete obj[name],用于删除对象的属性。
Reflect.has(target, name) //对应name in obj里面的in运算符。第一个参数不是对象,会报错。
Reflect.ownKeys(target) //用于返回对象的所有属性,基本等同于
Reflect.isExtensible(target) //返回一个布尔值,表示当前对象是否可扩展。
Reflect.preventExtensions(target) //用于让一个对象变为不可扩展。它返回一个布尔值,表示是否操作成功。
Reflect.getOwnPropertyDescriptor(target, name) //如果指定的属性存在于对象上,则返回其属性描述符对象
Reflect.getPrototypeOf(target) //方法用于读取对象的__proto__属性,不传对象会报错,对应Object.getPrototypeOf(obj)。
Reflect.setPrototypeOf(target, prototype) //用于设置目标对象的原型(prototype),对应Object.setPrototypeOf(obj, newProto)方法。它返回一个布尔值,表示是否设置成功。
设计目的:
重点:
Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大。
所谓Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。从语法上说,Promise 是一个对象,从它可以获取异步操作的消息。Promise 提供统一的 API,各种异步操作都可以用同样的方法进行处理。
Promise对象代表一个异步的操作,他的状态不受外界影响,只有结果可以决定返回哪一种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)
Promise的状态一旦发生改变,状态就凝固了称为 resolved 定型,
Promise无法取消,一旦新建他就会立即执行,无法中途取消
出参:
方法:
new Promise((resolved)=>resolved())
new Promise((resolved, rejected)=>rejected())
应用场景:加载图片、ajax转Promise对象
重点: