Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ECMAScript 6(三) Set数据结构 #11

Open
Alexandermclean opened this issue Mar 16, 2019 · 0 comments
Open

ECMAScript 6(三) Set数据结构 #11

Alexandermclean opened this issue Mar 16, 2019 · 0 comments
Labels
ES6 ECMAScript 6

Comments

@Alexandermclean
Copy link
Owner

3.Set数据结构

JavaScript 原有的表示“集合”的数据结构,主要是数组(Array)和对象(Object),ES6 又添加了Map和Set。

// 记住简单的用法就行
let set = new Set([1,2,2,3,3,4])
[...set]  // [1,2,3,4]
set.size // 4

实例化Set

ES6 提供了新的数据结构Set。它类似于数组,但是成员的值都是唯一的,没有重复的值。

const set = new Set([1,2,3,3,4,5])
console.log([...set])
// or

const set = new Set()
[1,2,3,3,4,5].forEach ((val, index) => {set.add(val)})
console.log([...set])
// 1,2,3,4,5  size:5

// 有个比较有意思的现象
// 直接add一个数组,而不是把数组元素一个个add
const set = new Set()
set.add([1,2,3,4,5,5])
console.log([...set])
// [1,2,3,4,5,5] size:1  会多一个一样的add的数组且可以含有重复元素

1.既可以在实例化Set的时候把数组当参数传进Set()构造函数,也可以用Set对象的add方法添加成员。
2.Set函数可以接受一个数组(或者具有 iterable 接口的其他数据结构)作为参数,用来初始化

特性和用法

1.针对Set数据结构元素不重复的特性,可以很简单的对数组去重

[...new Set(array)] // 去重array

也可以用于字符串去重

[...new Set('aabbccd')].join('') // 去重array

join() 方法用于把数组中的所有元素放入一个字符串,默认以逗号分割;可接受字符串参数x,即以x分割数组

2.向 Set 加入值的时候,不会发生类型转换,所以5和"5"是两个不同的值。Set内部判断两个值是否不同,使用的算法类似于精确相等运算符(===),主要的区别是在Set内部NaN等于自身,而精确相等运算符认为NaN不等于自身。

let set = new Set()
let a = NaN
let b = NaN
set.add(a)
set.add(b)
set // Set {NaN} 去重后

NaN === NaN // false

另外,两个对象总是不相等的。

let set = new Set();

set.add({})
set.size // 1

set.add({})
set.size // 2

{} === {} // false

Set实例的属性和方法

  1. Set 结构的实例有以下属性。

    • Set.prototype.constructor:构造函数,默认就是Set函数。
    • Set.prototype.size:返回Set实例的成员总数。
  2. Set 实例的方法分为两大类:操作方法(用于操作数据)和遍历方法(用于遍历成员)。下面先介绍四个操作方法。

    • add(value):添加某个值,返回 Set 结构本身。
    • delete(value):删除某个值,返回一个布尔值,表示删除是否成功。
    • has(value):返回一个布尔值,表示该值是否为Set的成员。
    • clear():清除所有成员,没有返回值。
s.add(1).add(2).add(2);
// 注意2被加入了两次

s.size // 2

s.has(1) // true
s.has(2) // true
s.has(3) // false

s.delete(2);
s.has(2) // false

另外,除了之前的[...set]这种方式把set类型转换成数组外,Array的from()方法也可以。

let set = new Set([1,2,2,3,3,4])
let arr = Array.from(set) // [1,2,3,4]

遍历操作

Set结构的实例有四个遍历方法,可以用于遍历成员。

  • keys():返回键名的遍历器
  • values():返回键值的遍历器
  • entries():返回键值对的遍历器
  • forEach():使用回调函数遍历每个成员

需要特别指出的是,Set的遍历顺序就是插入顺序。这个特性有时非常有用,比如使用Set保存一个回调函数列表,调用时就能保证按照添加顺序调用。

keys(),values(),entries()

keys方法、values方法、entries方法返回的都是遍历器对象(也就是Iterator对象)。由于Set结构没有键名,只有键值(或者说键名和键值是同一个值),所以keys方法和values方法的行为完全一致。

let set = new Set(['yu', 'zheng', 'hui']);

for (let item of set.keys()) {
  console.log(item);
}
// yu
// zheng
// hui

for (let item of set.values()) {
  console.log(item);
}
// yu
// zheng
// hui

for (let item of set.entries()) {
  console.log(item);
}
// ["yu", "yu"]
// ["zheng", "zheng"]
// ["hui", "hui"]

entries方法返回的遍历器,同时包括键名和键值,所以每次输出一个数组,它的两个成员完全相等。

另外,Set结构的实例默认可遍历,它的默认遍历器生成函数就是它的values方法。

Set.prototype[Symbol.iterator] === Set.prototype.values
// true

// 可以省略values方法,直接用for...of循环遍历 Set
for (let item of set) { // 等同于for (let item of set.values())
  console.log(item)
}
// yu
// zheng
// hui
forEach()

Set结构的实例与数组一样,也拥有forEach方法,用于对每个成员执行某种操作,没有返回值。

let set = new Set([1, 4, 9]);
set.forEach((val, key) => console.log(key + ' : ' + val))
// 1 : 1
// 4 : 4
// 9 : 9

Set的forEach方法的参数就是一个处理函数,该函数的参数与数组的forEach一致,依次为键值、键名、集合本身(上例省略了该参数)。这里需要注意,**Set结构的键名就是键值(两者是同一个值),**因此第一个参数与第二个参数的值永远都是一样的。

Array和Set组合应用

  1. 数组的map和filter方法也可以间接用于Set了
let set = new Set([1, 2, 3]);
set = new Set([...set].map(x => x * 2));
// 返回Set结构:{2, 4, 6}

let set = new Set([1, 2, 3, 4, 5]);
set = new Set([...set].filter(x => (x % 2) == 0));
// 返回Set结构:{2, 4}
  1. 使用Set可以很容易地实现并集(Union)、交集(Intersect)和差集(Difference)
let a = new Set([1, 2, 3])
let b = new Set([4, 3, 2])

// 并集
let union = new Set([...a, ...b])
// Set {1, 2, 3, 4}

// 交集
let intersect = new Set([...a].filter(x => b.has(x)))
// set {2, 3}

// 差集
let difference = new Set([...a].filter(x => !b.has(x)))
// Set {1}
@Alexandermclean Alexandermclean added the ES6 ECMAScript 6 label Mar 16, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
ES6 ECMAScript 6
Projects
None yet
Development

No branches or pull requests

1 participant