文章目录
前言
本篇博客我们继续深入了解es6那些我们没注意到的相关问题。
一、set和map
set集合常用作检查对象中是否存在某一个键名,并自身带有去重操作
map集合常用作获取已存在的信息
1.es5中基本操作如下
var set = {};
set.foo = true;
if(set.foo){
//....
}
var map = {};
map.foo = 200;
var value = map.foo;
console.log(value);
2.es6中使用
(1)es6中set集合
1> 创建和使用
还可以通过set.size查看元素个数,并且set集合自带去重效果,如上图代码,第二次添加5被忽略
2> 具体去重操作:
3> set=>Array
此时我们的原数组已经是set集合形式,我们如果想要再转变成数组,第一种操作如下,即执行Array.form操作:
我们还可以使用上篇(es6相关问题(1))博客介绍的三个点语法。
4> 删除元素
set还有一个clear()清空方法,即调用后set元素全部清空
5> 判断set集合是否含有某个元素
使用has方法判断
6> forEach方法
(2)es6中map集合
1> 创建和使用
使用new语法创建,set语法添加,set方法有两个参数,第一个是键名,第二个是键值。
2> 获取map集合中的某一些值
通过map.get()方法进行获取
3> 移除map集合中的元素
与set基本相同,使用delete删除,clear清空。
4> 初始化map集合
可以接受数组作为参数进行初始化。
5> map的forEach方法
map和set不同点之一就是map含有键而set没有,所以forEach方法传入参数(item,index)分别表示键值和键。
二、迭代器和生成器
1.迭代器
问题背景: 旨在消除这种复杂性和循环中的错误
如下循环,过多嵌套导致浪费时间
var arr = ['red' , 'blue' , 'yellow'];
for(var i = 0 ; i < arr.length ; i++){
for(var j = 0 ; j < arr.length ; j++){
for(var k = 0 ; k < arr.length ; k++){
}
}
}
迭代器是一种特殊的对象,它本身带有一个next()方法,这个方法会返回两个值如下:{value : 下一次要返回的值 , done : true / false}
首先使用es5创建迭代器:
function createInterator(items){ //es5手写了一个迭代器
var i = 0
return {
next : function(){
var done = (i >= items.length);
var value = !done ? items[i++] : undefined;
return {
done,
value
}
}
}
}
调用并打印结果如下:
2.生成器
es6中的生成器(generator)可以生成一个迭代器,所以可以说成是一种返回迭代器的函数。其具体的标志为函数名前面带一个*号,其使用yield所返回的结果作为迭代器的value存在 ,简单说明yield和return的区别:
return 1.返回一个函数的结果 2.跳出函数的运行
yield 1.返回一个函数的结果 2.暂停函数的运行
代码展示:
function *demo(){
console.log('a')
yield 1
console.log('b')
yield 2
console.log('c')
yield 3
console.log('d')
}
var init = demo(); //init是一个迭代器 next() -> {done,value}
console.log(init.next())
console.log(init.next())
console.log(init.next())
console.log(init.next())
打印结果如下:
此时的demo就是一个生成迭代器的函数,而init就是由生成器demo生成的迭代器。
再有如下样例代码,使用生成器对数组的迭代实现:
以下是生成器的实现框架:
function *uu(){}
var yy = function *(){}
//生成器在对象中的使用
var obj = {
fun : function *(){}
}
var obj1 = {
*ii(){
}
}
三、循环
1. for in
对于一个普通的对象,如下图,i相当于键名,而obj[i]就相当于键值。
这里简单介绍一下对象:
- 普通对象 object,可以使用for in 遍历
- 可迭代对象 string arr,可以使用for of 遍历
下面介绍 for of 用法。
2. for of
for of 的使用一般针对可迭代对象,如string,arr等,如下图程序,j就相当于str中的每个元素而不再是键名,而是相当于键值,遍历打印如下(对于数组也可以做同样的操作):
如上操作有些类似迭代器的输出,因为是可迭代对象,所以其内部相当于封装了一个迭代器,这个迭代器可以通过如下代码看到:
var arr = ['a','b','c'];
var init = arr[Symbol.iterator](); //init为arr的迭代器
console.log(init.next())
console.log(init.next())
console.log(init.next())
console.log(init.next())
即封装一个数组arr,使用Symbol.iterator(相当于一个生成器,其结果会返回一个迭代器),所以此时的init就相当于一个迭代器了,则打印结果如下:
判断一个对象是否是可迭代对象?
- 判断是否含有Symbol.iterator
- Symbol.iterator是否是一个函数
判断代码示例:
对于str其是一个可迭代对象,所以输出true,但{}不是,所以输出了undefined
虽然普通的{}对象不是可迭代对象,但是可以通过给他添加Symbol.iterator的方法使其变成可迭代对象。
如下代码运行在控制台上:
var obj6 = {
item : [1,2,3],
*[Symbol.iterator](){
for(var u = 0 ; u < this.item.length ; u++){
yield this.item[u]
}
}
};
for(var t of obj6){
console.log(t)
}
结果如下所示:
本身对象是不可迭代对象,所以无法使用for of遍历,但是在其本身内部写下item即值的定义,再添加迭代器(由Symbol.iterator生成的)就可以变成可迭代对象了。
按照可迭代对象的特点 ,我们不难想到如下代码:
var init2 = obj6[Symbol.iterator]();
console.log(init2.next())
console.log(init2.next())
console.log(init2.next())
console.log(init2.next())
没错,就是对可迭代对象中迭代器的表示,运行结果如下:
四.es6内置的一些迭代器
1. entries()
使用这个内置迭代器,不仅会返回值,还会返回其下标,如下遍历数组的代码。
var arr = ['a','b','c'];
for(var i of arr){ //
console.log(i)
}
for(var j of arr.entries()){
console.log(j)
}
最后打印结果是以数组形式返回下标和值:
上面是对数组的遍历,我们再分别对set和map进行遍历:
(1)set
由下面结果可以看出,打印的结果键值和键名是一样的
(2)map
map的遍历结果和自己的迭代器遍历结果一样
2. values()
values会遍历对象所存的所有的值,所以遍历arr和set结果都是一样的,(都是取值),对于遍历map结果就是只取出了键值:
3. keys()
返回的是键。如遍历map:
而遍历set时,set没有索引值,所以结果和正常遍历一样:
最后是arr,arr的索引值就是下标:
五、es6对于数组的改进
1.创建数组
es6之前,我们创建数组有以下两种方法:
var arr = [1,2,3];//直接创建
var arr1 = new Array(1,2,3)//使用构造函数
以前的创建会存在一些bug,例如在使用构造函数创建时,如下代码:
var arr1 = new Array(3)
正常来讲,我们的理解是创建了只包含一个元素3的数组,但打印结果:
这说明其理解为了创建一个长度为3,值为空的数组。
Array.of()
创建单个元素数组,如下:
2.es6数组新添加的方法
(1)find()
查找一个元素的下标的两种方法:indexOf、lastIndexOf。
indexOf指的是从前向后遍历,找到的第一个出现的元素的下标。
lastIndexOf则是从后向前遍历,找到第一个出现的元素的下标。
代码如下:
由此可见两者的查找并不是很严谨,这里再介绍另一个查找方法:find()
Array.find((item,index)=>{
//item要查找的值
//index 下标
})
具体示例:
可以发现,find可以根据条件查找相应的第一个元素
(2)findIndex
findIndex查找满足条件的第一个元素的下标
具体示例如下:
(3)fill
填充,传入三个参数fill(item,left,right)
item是你要填充的值,[left,right)是要填充进去的区间,区间是左闭右开的,如下(将2,3填充成了0,也相当于是一种替换):