大家好混元霹雳手Ziksang又来了,给大家讲讲es6,Set这个新的数据结构
大年初三,先给大家拜个年,我知道我的拜方式错了!!红包即将打到你的支付宝中,请接收!
2017年的目标就是把ecmscript6所有的知识点全弄明白,我相信以后会基于ecmascript6的新特性肯定会出一些更牛B的框架,就像vue一样用了Object.defineProperty ecmascript5的新特性来进行数据劫持,所以我很期待
简单介绍一下吧
Set基本介绍
Set是ES6中数据结构中其中一个新的特性,我们看上去往往很像数组,但是他的每个成员都是唯一的,不会存在重复的值
Set也是一个构造函数,用来生成Set这个数据结构,我们可以看看他实例原型上有那些东西,简单看一下
在set原型上放了这么多方法,接下来我一一介绍一下吧,记住学习一定要学到根本!!!!
注意我的每一步代码都是自上而下有着关联的
add方法
let set = new Set()
let array = [1,"ziksang",3,3,true,5,5]
array.forEach(item => {
set.add(item)
})
console.log(set)
// Set {1, "ziksang", 3, true, 5}
1.先new出set这个构造函数实列,我们存在set变量上
2再声明一个array这个数组,里面的数组成员有各种数据类型和重复的值
3.用Set原型上add方法把用es5中each方法把每个值添加到set成员里
4.打印出来是一个对象,里面相同类型相同值都会去掉,但是里面的整体结构和类组数对象一样,有着自己的长度
for (let i of set) {
console.log(i);
console.log(typeof i)
}
以上我们再次用for of的方法也,同样也是es6的新特性,此时就可以把set对象里每一个值可以打印出来,里面的打印出的每一个数据类型也同样是我们array数组里定义的数据类型
上面代码通过add方法向Set结构加入成员,结果表明Set结构不会添加重复的值。
Set函数可以接受一个数组(或类似数组的对象)作为参数,用来初始化。
function demo(){
let set = new Set(arguments)
console.log(set)
}
demo(1,2,4,4,5)
//Set {1, 2, 4, 5}
let set = new Set([1,2,4,4,5])
console.log(set)
//Set {1, 2, 4, 5}
1.Set函数里我们可以接受参数来作为初始化跟new Array[1,2,3,4]性质是一样的
2.第一个我在demo函数里让set函数接收了demo里arguments对象作为参数
3.第二个我直接在set函数里放入一个数组
4.两都console.log()打印出来的是一样的,同样不会包含同类型同样的值的成员
size方法
size方法是用来判断出,set里成员的个数
var items = new Set([1, 2, 3, 4, 5, 5, 5, 5]);
items.size // 5
1.虽然上面我定义了8个成员数量,但是最后个数只有5个,因为还是同样的不会把重复同类型同样的值算进去,只算一个
数组去重方法
在以前数我面试的时候别人一直接我数组去重怎么样,我现在只想回答他,看下面
let array = [1,2,2,3,3,4]
let set = new Set(array)
array = [...set]
console.log(array)
//[1,2,3,4]
1.声明一个数组
2.把数组作为set构造函数的初始化成员
3.再把set用[...set]来重新复制给array//简称拓展运算符...
4.扩展运算符(...)内部使用for...of循环,所以也可以用于Set结构。
关于类型转换,NaN,object的区别
在往set数据结构中添加值的值,并不会发生类型转换,4和“4”不同的数据类型不会发生转换,他的内部是用Same-value equality
,也就是跟恒等差不多,但是NaN不一样很特殊
console.log(NaN === NaN) //false
const a = NaN;
const b = NaN;
const c = "1";
const d = 1;
let set = new Set()
set.add(a)
set.add(b)
set.add(c)
set.add(d)
console.log(set) //Set {NaN, "1", 1}
1.如果单纯的比对NaN === NaN肯定是不相等的,但是在set数据结构中,里面的计算原理是把NaN看成相等的
对于两个对象来说,无是里面是否有值 ,可者有什么样的值都是不相等的,空对象也不相等
let set = new Set()
set.add({})
set.add({})
console.log(set) //Set {Object {}, Object {}}
console.log(set.size)//2
1.可以看出空对象是不相等的,所以它们被视为两个值。总个数依然是2个
Set实例的属性和方法,也就是Set构造函数上定义的方法和属性
Set结构的实例有以下属性。
Set.prototype.constructor:构造函数,默认就是Set函数。
Set.prototype.size:返回Set实例的成员总数。
Set实例的方法分为两大类:操作方法(用于操作数据)和遍历方法(用于遍历成员)。下面先介绍四个操作方法。
add(value):添加某个值,返回Set结构本身。
delete(value):删除某个值,返回一个布尔值,表示删除是否成功。
has(value):返回一个布尔值,表示该值是否为Set的成员。
clear():清除所有成员,没有返回值。
size和add我在前面已经讲过了,再少许提一下吧
let set = new Set()
set.add(3).add(2).add(2).add("ziksang");
console.log(set)//set{3,2,ziksang}
console.log(set.has(3)) //true
console.log(set.delete(2)) //true
console.log(set) //set{3,ziksang}
console.log(set.clear()) //undefined
console.log(set) //set{}
1.我们new出Set构造函数的实列对象进行一个一个add进行添加,但是添加了两个同类型同样值 的2 !最后打印出来同样的一个会被去除
2.set.has()是进行对set数据结构中成员是否存在的判断
3.删除set数据结构中成员
4set.clear()是进行清除所有成员,set实列也因此成为了一个空对象
不同对比的例子,看看Object和Set两个数据结构判断方式不同
let obj={
name : "ziksang",
age : 22
}
let set = new Set(["name",22])
if(obj.name){
console.log("在对象里有name这个健值")
}
if(set.has("name")){
console.log("set数据结构中有name这个成员")
}
提示
1.[阮一峰]用obj[somename]来判断是否对象里有这个健,打出来是undefined,以上修正了一下
2.判断set数据结构中是否有某个成员,用set.has()来判断
另外再介绍一下另一种数组去重方式
Array.from()是es6数组中新带的一个方法
function demo(array){
return Array.from(new Set(array))
}
let result = demo([1,1,2,2,3])
console.log(result)//1,2,3
Array.from是什么鬼以后具体讲到es6数组我给大家讲讲,我现在只知其一,不知其二,讲不透彻的就不给大家讲
遍历操作
Set结构的实例有四个遍历方法,可以用于遍历成员。
keys():返回键名的遍历器
values():返回键值的遍历器
entries():返回键值对的遍历器
forEach():使用回调函数遍历每个成员
需要特别指出的是,Set的遍历顺序就是插入顺序。这个特性有时非常有用,比如使用Set保存一个回调函数列表,调用时就能保证按照添加顺序调用。
keys方法、values方法、entries方法返回的都是遍历器对象,因为set没有健名只有健值 ,所以健名和健值可以说是同一个值 ,keys和values返回的都是同一个值
let set = new Set([1,2,3,4])
for(item of set.keys()){
console.log(item) //1,2,3,4
}
for(item of set.values()){
console.log(item) //1,2,3,4
}
for(item of set.entries()){
console.log(item) //[1,1],[2,2],[3,3],[4,4]
console.log(typeof item)//都是object对象
}
1.keys,values,entries()返回的都是遍历器对象
2.entries返回的是健值对,因为为健和值都是一样的,所以里面两个也一样,但是返回出来是是一个对象,本值 上是一个类数组对象
Set结构的实例默认可遍历,它的默认遍历器生成函数就是它的values方法。第一个张图我也打印出prototype原型上的方法和属性里,里面的symbol.iterator里是values()所以也可以直接for of Set构造函数返回的实例
Set.prototype[Symbol.iterator] === Set.prototype.values
// true
let set = new Set([1,2,3,4])
for(item of set){
console.log(item) //1,2,3,4
}
可以看出我们直接遍历SET实例和调用value()返回的遍历器对象是一样的
forEach()
Set结构的实例的forEach方法,用于对每个成员执行某种操作,没有返回值。
let set = new Set([1,2,3,4])
set.forEach(function(value,key){
console.log(value*key) //1,4,9,16
})
上面代码说明了,对set实例里的健和值互乘,其实value和key都是一个值
数组的map和filter方法也可以用set上
let set = new Set([1,2,3])
set = new Set([...set].map(item => item*2))
console.log(set) //{2,4,6}
set2 = new Set([...set].filter(item =>item>3))
console.log(set2)//{4,6}
给大家解释一下用了那些关键方法
1[...set]把set实例进行转成数组再用map方法把线个值乘2给返回当作Set函数里的成员
2.filter方法也是同理,只是对数组 的值 进行筛选再返回
因此使用Set可以很容易地实现并集(Union)、交集(Intersect)和差集(Difference)。
1.并集Union
let a = new Set([1,2,3,4,5])
let b = new Set([1,2,3,6,7])
let set = new Set([...a,...b])
console.log(set) //1,2,3,4,5,6,7
上面把a,b里遍历出来在放入数组,再用set的特性进行去重
2.交集
let a = new Set([1,2,3,4,5])
let b = new Set([1,2,3,6,7])
let intersect = new Set([...a].filter(x => b.has(x)))
console.log(intersect) //{1,2,3}
上面是把a进行转化成数组用filter进行过滤,过滤的返回结果是b里面有的值
差集
let a = new Set([1,2,3,4,5])
let b = new Set([1,2,3,6,7])
let intersect = new Set([...a].filter(x => !b.has(x)))
console.log(intersect) //{4,5}
上面是把a进行转化成数组用filter进行过滤,过滤的返回结果是b里面没有的值
如果想在遍历操作中,同步改变原来的Set结构,目前没有直接的方法,但有两种变通方法。一种是利用原Set结构映射出一个新的结构,然后赋值给原来的Set结构;另一种是利用Array.from方法。
// 方法一
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
第一个方法本质上是把set重新进行赋值,先把原先的set里面的成为用[...set]化为数组再用map来进行重新操作再返回给set构造函数的成员
第二个方法等我弄懂了再告诉大家
这里我大部分都是按着阮一锋老师的书籍来进行分析,讲的好的我就记录下来,再用更白的话跟大家讲,有些不清楚说的模糊 的地方也更清楚的跟大家解释明白了,接下来我会把阮一锋老师 ES6所有的知识点都给大家搞明白,搞透彻