ES6(超详细)3—持续更新中~

123 阅读6分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 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()方法返回的是一个对象,对象中包括valuedone属性,前者代表的是当前遍历到的属性,后者是一个布尔值,表示的是当前是否遍历完。可以将其理解为一个指针,从序列的开头元素开始,逐个执行next()方法,知道指针指向最后undefineddone为 true 时,结束遍历,这也是for循环的底层实现原理

既然扯到这了就顺带提一下for循环:

  1. for...of用于遍历键值
const test=['A','B','C','D'];

for(let i of test){
    console.log(i)  
}

  1. 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...offor...in的区别即可

11. 生成器

  • 生成器函数是ES6提供的一种异步编程解决方案,语法行为与传统函数完全不同,是一种特殊的函数 ,这种函数的函数名和function中间有一个*,而函数内部有yield来作为代码的分隔符
  • 这里的*yield有点类似后面要讲的Promise中的asyncawait,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对象

  1. 当回调后,返回的是非Promise类型的属性时,状态为fulfilled,then()函数返回对象的状态为fulfilled,如果throw 123,返回的Promise对象状态为rejected,如果没有返回值,则返回的Promise对象状态未被改变还是pending
  2. 当回调后,返回的是Promise类型的对象时,then()函数的返回值为这个Promise对象的状态值
  3. 当回调后,如果抛出的异常,则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专题持续更新中~