大家好混元霹靂手Ziksang又來了,給大家講講es6,Set這個新的數據結構
大年初三,先給大家拜個年,我知道我的拜方式錯了?。〖t包即將打到你的支付寶中,請接收!
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所有的知識點都給大家搞明白,搞透徹