let/const
let/const用于声明变量,替代老语法的var关键字,它的用法与var类似,但是所声明的变量只在所在的代码块中有效。
let/const与var的主要区别:
- 不允许重复声明
- 未定义就使用会报错:
let/const不存在变量提升现象 - 暂时性死区:在代码块内使用
const命令和let命令声明变量之前,该变量都不可用
const
与let不相同的是,const声明的是一个只读常量。
const的特点:
const与let不同,const声明后必须立马赋值,只声明不赋值就会报错const是一个只读常量,并不是变量的值不改变,而是变量指向的那个内存地址不改变。- 对于简单类型的数据(数值、字符串、布尔值),就相当于常量
- 对于复合类型的数据(数组、对象),变量指向内存地址,
const实际保存的是指向实际数据的指针,它只能保证指针不变,不能保证,指针里的内容不变,
解构赋值
多种解构
字符串解构
字符串也可以解构赋值。这是因为此时,字符串被转换成了一个类似数组的对象。
const [a, b, c, d, e] = 'hello';
数值和布尔值解构
解构赋值时,如果等号右边是数值和布尔值,则会先转为对象。
let {toString: s} = 123;
s === Number.prototype.toString // true
let {toString: s} = true;
s === Boolean.prototype.toString // true
对象解构
对象的属性没有次序,变量必须与属性同名,才能取到正确的值。
形式:const { x, y } = { x: 1, y: 2 }
默认:const { x, y = 2 } = { x: 1 }
改名:const { x, y: z } = { x: 1, y: 2 }
数组解构
只要某种数据结构具有Iterator接口就可采用数组形式的解构赋值
形式:const [x, y] = [1, 2]
默认:const [x, y = 2] = [1]
函数参数解构
//数组参数解构
function add([x, y]){
return x + y;
}
add([1, 2]); // 3
//对象参数解构且有默认值
function move({x = 0, y = 0} = {}) {
return [x, y];
}
move({x: 3, y: 8}); // [3, 8]
move({x: 3}); // [3, 0]
move({}); // [0, 0]
move(); // [0, 0]
应用场景
-
交换变量值:
[x, y] = [y, x] -
返回函数多个值:
const [x, y, z] = Func() -
定义函数参数:
Func([1, 2]) -
提取JSON数据:
const { name, version } = packageJson -
定义函数参数默认值:
function Func({ x = 1, y = 2 } = {}) {} -
遍历Map结构:
for (let [k, v] of Map) {} -
输入模块指定属性和方法:
const { readFile, writeFile } = require("fs")
重点
- 匹配模式:只要等号两边的模式相同,左边的变量就可以赋给右边
- 解构赋值规则:只要右边不是对象或者数组,就会将其转换为对象
- 解构不成功时,变量的值为
undifined undifined与null无法转为对象,因此无法赋值
箭头函数
ES6 允许使用箭头(=>)定义函数,简化定义函数
var f = v => v;
// 等同于
var f = function (v) {
return v;
};
- 无参数:
() => {} - 单个参数:
x => {} - 多个参数:
(x, y) => {} - 解构参数:
({x, y}) => {}
重点
-
函数体内的
this对象,就是定义时所在的对象,而不是使用时所在的对象。 -
不可以当作构造函数,也就是说,不可以使用
new命令,否则会抛出一个错误。 -
不可以使用
arguments对象,该对象在函数体内不存在。如果要用,可以用 rest 参数代替。
数组的扩展
扩展运算符(...):转换数组为用逗号分隔的参数序列([...arr],相当于rest/spread参数的逆运算)
Array.from():转换具有Iterator接口的数据结构为真正数组,返回新数组
类数组对象:包含length的对象、Arguments对象、NodeList对象
可遍历对象:String、Set结构、Map结构、Generator函数
Array.of():转换一组值为真正数组,返回新数组
copyWithin():把指定位置的成员复制到其他位置,返回原数组
find():返回第一个符合条件的成员
findIndex():返回第一个符合条件的成员索引值
fill():根据指定值填充整个数组,返回原数组
keys():返回以索引值为遍历器的对象
values():返回以属性值为遍历器的对象
entries():返回以索引值和属性值为遍历器的对象
数组空位:ES6明确将数组空位转为undefined(空位处理规不一,建议避免出现)
扩展运算符的应用
克隆数组:const arr = [...arr1]
合并数组:const arr = [...arr1, ...arr2]
拼接数组:arr.push(...arr1)
代替apply:Math.max.apply(null, [x, y]) => Math.max(...[x, y])
转换字符串为数组:[..."hello"]
转换类数组对象为数组:[...Arguments, ...NodeList]
转换可遍历对象为数组:[...String, ...Set, ...Map, ...Generator]
与数组解构赋值结合:const [x, ...rest/spread] = [1, 2, 3]
计算Unicode字符长度:Array.from("hello").length => [..."hello"].length
Set
- 定义:类似于数组的数据结构,成员值都是唯一且没有重复的值
- 声明:
const set = new Set(arr) - 入参:具有
Iterator接口的数据结构 - 属性
- constructor:构造函数,返回Set
- size:返回实例成员总数
- 方法
- add():添加值,返回实例
- delete():删除值,返回布尔
- has():检查值,返回布尔
- clear():清除所有成员
- keys():返回以属性值为遍历器的对象
- 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(arr) - 映射:
set = new Set([...set].map(v => v * 2))或set = new Set(Array.from(set, v => v * 2))
- 声明:
重点难点
- 遍历顺序:插入顺序
- 没有键只有值,可认为键和值两值相等
- 添加多个
NaN时,只会存在一个NaN - 添加相同的对象时,会认为是不同的对象
- 添加值时不会发生类型转换(
5 !== "5") keys()和values()的行为完全一致,entries()返回的遍历器同时包括键和值且两值相等
WeakSet
- 定义:和Set结构类似,成员值只能是对象
- 声明:
const set = new WeakSet(arr) - 入参:具有
Iterator接口的数据结构 - 属性
- constructor:构造函数,返回WeakSet
- 方法
- add():添加值,返回实例
- delete():删除值,返回布尔
- has():检查值,返回布尔
应用场景
- 储存DOM节点:DOM节点被移除时自动释放此成员,不用担心这些节点从文档移除时会引发内存泄漏
- 临时存放一组对象或存放跟对象绑定的信息:只要这些对象在外部消失,它在
WeakSet结构中的引用就会自动消
重点难点
- 成员都是
弱引用,垃圾回收机制不考虑WeakSet结构对此成员的引用 - 成员不适合引用,它会随时消失,因此ES6规定
WeakSet结构不可遍历 - 其他对象不再引用成员时,垃圾回收机制会自动回收此成员所占用的内存,不考虑此成员是否还存在于
WeakSet结构中
Map
- 定义:类似于对象的数据结构,成员键是任何类型的值
- 声明:
const set = new Map(arr) - 入参:具有
Iterator接口且每个成员都是一个双元素数组的数据结构 - 属性
- constructor:构造函数,返回Map
- size:返回实例成员总数
- 方法
- get():返回键值对
- set():添加键值对,返回实例
- delete():删除键值对,返回布尔
- has():检查键值对,返回布尔
- clear():清除所有成员
- keys():返回以键为遍历器的对象
- values():返回以值为遍历器的对象
- entries():返回以键和值为遍历器的对象
- forEach():使用回调函数遍历每个成员
重点难点
- 遍历顺序:插入顺序
- 对同一个键多次赋值,后面的值将覆盖前面的值
- 对同一个对象的引用,被视为一个键
- 对同样值的两个实例,被视为两个键
- 键跟内存地址绑定,只要内存地址不一样就视为两个键
- 添加多个以
NaN作为键时,只会存在一个以NaN作为键的值 Object结构提供字符串—值的对应,Map结构提供值—值的对应
WeakMap
- 定义:和Map结构类似,成员键只能是对象
- 声明:
const set = new WeakMap(arr) - 入参:具有
Iterator接口且每个成员都是一个双元素数组的数据结构 - 属性
- constructor:构造函数,返回WeakMap
- 方法
- get():返回键值对
- set():添加键值对,返回实例
- delete():删除键值对,返回布尔
- has():检查键值对,返回布尔
应用场景
- 储存DOM节点:DOM节点被移除时自动释放此成员键,不用担心这些节点从文档移除时会引发内存泄漏
- 部署私有属性:内部属性是实例的弱引用,删除实例时它们也随之消失,不会造成内存泄漏
重点难点
- 成员键都是
弱引用,垃圾回收机制不考虑WeakMap结构对此成员键的引用 - 成员键不适合引用,它会随时消失,因此ES6规定
WeakMap结构不可遍历 - 其他对象不再引用成员键时,垃圾回收机制会自动回收此成员所占用的内存,不考虑此成员是否还存在于
WeakMap结构中 - 一旦不再需要,成员会自动消失,不用手动删除引用
- 弱引用的
只是键而不是值,值依然是正常引用 - 即使在外部消除了成员键的引用,内部的成员值依然存在
Promise
- 定义:Promise是一种异步编程的解决方案。从语法上来讲,Promise是一个对象,他可以获取异步操作的的消息。从本意上来讲,Promise是一个承诺,承诺过一段时间后给你一个结果。Promise有三种状态:pending(等待),fulfiled(成功),rejected(失败),状态一旦改变,就不会再变。
- 状态:
- 进行中:pending
- 已成功:fulfilled
- 已失败:rejected
- 特点:
- 对象的操作不受外界的影响
- 一旦状态改变,任何时候都会得到这个结果
- 示例:
const promise = new Promise(function(resolve, reject) {
// ... some code
if (/* 异步操作成功 */){
resolve(value);
} else {
reject(error);
}
});
-
出参
- resolve:将状态从
未完成变为成功,在异步操作成功时调用,并将异步操作的结果作为参数传递出去 - reject:将状态从
未完成变为失败,在异步操作失败时调用,并将异步操作的错误作为参数传递出去
- resolve:将状态从
-
方法:
-
then():分别指定
resolved和rejected状态的回调函数- 第一参数:状态变为
resolved时调用 - 第二参数:状态变为
rejected时调用
- 第一参数:状态变为
-
catch():用于指定发生错误时的回调函数。
-
Promise.all():将多个实例包装成一个新实例,返回全部实例状态变更后的结果数组(齐变更再返回)
- 入参:具有
Iterator接口的数据结构 - 成功:只有全部实例状态变成
fulfilled,最终状态才会变成fulfilled - 失败:其中一个实例状态变成
rejected,最终状态就会变成rejected
- 入参:具有
-
Promise.race():将多个实例包装成一个新实例,返回全部实例状态优先变更后的结果(先变更先返回)
- 入参:具有
Iterator接口的数据结构 - 成功失败:哪个实例率先改变状态就返回哪个实例的状态
- 入参:具有
-
Promise.resolve():将对象转为Promise对象(等价于
new Promise(resolve => resolve()))- Promise实例:原封不动地返回入参
- Thenable对象:将此对象转为Promise对象并返回(Thenable为包含
then()的对象,执行then()相当于执行此对象的then()) - 不具有then()的对象:将此对象转为Promise对象并返回,状态为
resolved - 不带参数:返回Promise对象,状态为
resolved
-
Promise.reject():将对象转为状态为
rejected的Promise对象(等价于new Promise((resolve, reject) => reject()))
-
应用场景
-
加载图片
-
AJAX转Promise对象
重点难点
-
只有异步操作的结果可决定当前状态是哪一种,其他操作都无法改变这个状态
-
状态改变只有两种可能:从
pending变为resolved、从pending变为rejected -
一旦新建
Promise对象就会立即执行,无法中途取消 -
不设置回调函数,内部抛错不会反应到外部
-
当处于
pending时,无法得知目前进展到哪一个阶段 -
实例状态变为
resolved或rejected时,会触发then()绑定的回调函数 -
resolve()和reject()的执行总是晚于本轮循环的同步任务 -
then()
返回新实例,其后可再调用另一个then() -
then()运行中抛出错误会被catch()捕获 -
reject()的作用等同于抛出错误 -
实例状态已变成
resolved时,再抛出错误是无效的,不会被捕获,等于没有抛出 -
实例状态的错误具有
冒泡性质,会一直向后传递直到被捕获为止,错误总是会被下一个catch()捕获 -
不要在
then()里定义rejected状态的回调函数(不使用其第二参数) -
建议使用
catch()捕获错误,不要使用then()第二个参数捕获 -
没有使用
catch()捕获错误,实例抛错不会传递到外层代码,即不会有任何反应 -
作为参数的实例定义了
catch(),一旦被rejected并不会触发Promise.all()的catch() -
Promise.reject()的参数会原封不动地作为rejected的理由,变成后续方法的参数
for...of循环
-
定义:调用
Iterator接口产生遍历器对象(for-of内部调用数据结构的Symbol.iterator()) -
遍历字符串:
for-in获取索引,for-of获取值. -
遍历数组:
for-in获取索引,for-of获取值 -
遍历Set:
for-of获取值=>for (const v of set) -
遍历Map:
for-of获取键值对=>for (const [k, v] of map),for-of获得到的是一个由键与值构成的数组let map = new Map().set('a', 1).set('b', 2); for (let pair of map) { console.log(pair); } // ['a', 1] // ['b', 2] for (let [key, value] of map) { console.log(key + ' : ' + value); } // a : 1 // b : 2 -
遍历对象:
for-in获取键,for-of需自行部署for-of并不能直接遍历对象,如果直接遍历会报错。我们需要部署Iterator接口。遍历对象还是使用for-in更好一点- 使用
Object.keys方法将对象的键名生成一个数组,然后遍历这个数组。
for (var key of Object.keys(someObject)) { console.log(key + ': ' + someObject[key]); }- 使用 Generator 函数将对象重新包装一下。
function* entries(obj) { for (let key of Object.keys(obj)) { yield [key, obj[key]]; } } for (let [key, value] of entries(obj)) { console.log(key, '->', value); } // a -> 1 // b -> 2 // c -> 3 - 使用
-
与
for-in区别- 有着同
for-in一样的简洁语法,但不会像for-in一样会遍历原型上的属性。 for-of会以添加顺序来进行遍历,而不会像for-in以任意顺序遍历- 不同于
forEach(),它可与break、continue和return配合使用 - 提供遍历所有数据结构的统一操作接口
- 有着同