持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第7天,点击查看活动详情
ES6专题所有文章:
ES6-1(let、const、解构赋值、模板字符串、对象简化写法、箭头函数) ES6-2(函数默认参数、扩展运算符、rest参数、Symbol) ES6-3(迭代器、生成器、Promise、Set、Map) ES6-4(Class、数值扩展、对象方法扩展、模块化)
10. 迭代器
- 迭代器(lterator)是一种接口,为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署lterator接口,就可以完成遍历操作
- 原理:创建一个指针对象,指向数据结构的起始位置,第一次调用next()方法,指针自动指向数据结构第一个成员,接下来不断调用next(),指针一直往后移动,直到指向最后一个成员,没调用next()返回一个包含value和done属性的对象
const test=['A','B','C','D'];
let iterator = test[Symbol.iterator]();
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
由以上示例可以看出:迭代器每次调用next()方法返回的是一个对象,对象中包括value和done属性,前者代表的是当前遍历到的属性,后者是一个布尔值,表示的是当前是否遍历完。可以将其理解为一个指针,从序列的开头元素开始,逐个执行next()方法,知道指针指向最后undefined,done为 true 时,结束遍历,这也是for循环的底层实现原理
既然扯到这了就顺带提一下for循环:
for...of用于遍历键值
const test=['A','B','C','D'];
for(let i of test){
console.log(i)
}
for...in用于遍历键名
const test=['A','B','C','D'];
for(let i of test){
console.log(i)
}
注意: 数组的键名就是对应的索引值,所以这里输出0、1、2、3
for循环就是在内部不断调用迭代器的next()方法去逐个访问,知道返回的对象中done值为true才结束遍历
所以这一部分只是为了帮助你更好的了解for循环的原理,在平时一般会使用for循环遍历,并且能够区分for...of和for...in的区别即可
11. 生成器
- 生成器函数是ES6提供的一种异步编程解决方案,语法行为与传统函数完全不同,是一种特殊的函数 ,这种函数的函数名和function中间有一个
*,而函数内部有yield来作为代码的分隔符 - 这里的
*和yield有点类似后面要讲的Promise中的async和await,yield的作用是将函数内部的代码分段,每调用一次next()方法便执行一段,并且将yield后面的数据作为返回对象的value,同时返回的对象中也会有done属性,因为这也是利用迭代器实现的
function * test (){
console.log('第一段')
yield '小明';
console.log('第二段');
yield '小王';
console.log('第三段');
yield '小红';
console.log('第四段');
}
let iterator = test();
console.log(iterator.next());
//{value:'耳朵',done:false} next()执行第一段,并且返回yield后面的值
console.log(iterator.next());
显然,只调用了两次next(),所以函数只执行了两段,这样就实现了将这个函数变为异步的,因为你可以随时在调用其他函数的时候调用此函数中的一段代码,而且该函数中的代码也会按顺序执行,所以如果内部的代码本身就是异步的,为防止不同的代码之间存在依赖关系(如数据请求),可以通过这种方法将其转换为类似同步的不同代码片段
12. Promise
- Promise是ES6引入的异步编程的新解决方案。语法上 Promise是一个构造函数,用来封装异步操作
- 每一个Promise对象都有一个对应的状态,状态的初始值是
pending,可以通过resolve()将其设置为fulfilled成功状态,也可以通过reject()方法设置为rejected失败状态 - 基本特性
const p =new Promise((resolve, reject)=>{
setTimeout(()=>{
let data='数据库数据'
if(...){
resolve(data);
}else{
reject(data);
}
},500)
})
p.then(function (value){ //成功则执行第一个回调函数,失败则执行第二个
console.log(value)
},function (reason){
console.error(reason)
})
图源:MDN官网
- Promise.then()方法
const p =new Promise((resolve, reject) =>{
setTimeout(()=>{
resolve('用户数据');
})
});
let result = p.then(value => {
console.log(value)
// return new Promise((resolve, reject) => {
// resolve('ok')
// })
throw 123
},reason => {
console.log(reason)
})
console.log(result);
then() 函数返回的实际也是一个Promise对象
- 当回调后,返回的是非Promise类型的属性时,状态为fulfilled,
then()函数返回对象的状态为fulfilled,如果throw 123,返回的Promise对象状态为rejected,如果没有返回值,则返回的Promise对象状态未被改变还是pending - 当回调后,返回的是Promise类型的对象时,
then()函数的返回值为这个Promise对象的状态值 - 当回调后,如果抛出的异常,则then()函数的返回值状态也是
rejected
- Promise.catch()方法
//catch()函数只有一个回调函数,意味着如果Promise对象状态为失败就会调用catch()方法并且调用回调函数
<script>
const p = new Promise((resolve, reject) => {
setTimeout(()=>{
reject('出错啦')
},1000)
})
p.catch(reason => {
console.log(reason)
})
</script>
catch() 函数可以捕获到Promise链上的错误,并且将错误信息作为参数传入其回调函数中
- catch函数就相当于没有传入resolve回调函数的then函数
13. Set
- ES6提供了新的数据结构set(集合)。它类似于数组,但成员的值都是唯一的,集合实现了iterator接口,所以可以使用【扩展运算符】和【for...of】进行遍历
集合的属性和方法:
- size:返回集合的元素个数
- add:增加一个新元素,返回当前集合
- delete:删除元素,返回boolean值has检测集合中是否包含某个元素,返回boolean值
- clear:清空Set
let s = new Set();
let s2 = new Set(['A','B','C','D'])
//元素个数
console.log(s2.size);
//添加新的元素
s2.add('E');
//删除元素
s2.delete('A')
//检测
console.log(s2.has('C'));
//清空
s2.clear()
console.log(s2);
- 由于
Set内元素的唯一性,该容器经常被用于数组去重:
const numbers = [2,3,4,4,2,3,3,4,4,5,5,6,6,7,5,32,3,4,5]
let unique = [...new Set(numbers)]
- 可以用于将
string字符串按每个字符拆分并装到Set容器中
let str = 'helloworld'
let mySet = new Set(str)
console.log(mySet)
14. Map
- ES6提供了Map数据结构。它类似于对象,也是键值对的集合。但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。Map也实现了iterator接口,所以可以使用【扩展运算符】和【for...of】进行遍历。
Map的属性和方法:
- set:用于设置Map中对应键名的键值
- size:返回Map中的键值对个数
- delete:删除Map中的某一个键值对,传入的参数是键名
- clear:清空Map
let m = new Map();
m.set('name','小明');
m.set('change',()=>{
console.log('123')
})
let key={
name:'xiaoming'
}
m.set(key,['男',12]);
//size
console.log(m.size);
//删除
m.delete('name');
//获取
console.log(m.get('change'));
// //清空
// m.clear()
//遍历
for(let v of m){
console.log(v);
}
哈喽!这里是Crizz的前端之旅~
ES6专题持续更新中~