Skip to content

Latest commit

 

History

History
294 lines (210 loc) · 6.8 KB

08. 新数据结构.md

File metadata and controls

294 lines (210 loc) · 6.8 KB

新数据结构

1. Set

Set 类似于数组,是一种集合的数据结构,但Set中所有的成员都是唯一的。

img

Set 本身是一个构造函数,用来生成 Set 数据结构

const s1 = new Set()
s1.add(1)
s1.add(2)
s1.add(1)
// s1 的值为 {1, 2}

Set 函数可以接受一个可循环的数据结构(如数组、类数组、含有 iterable 接口 的其他数据结构)作为参数来初始化:

const s2 = new Set([1,2,1,4,3,4])
// s2 的值为 {1, 2, 3, 4}

1.1 Set属性及操作方法

  • size
    onst s2 = new Set(['a','b','c','d'])
    // s2 的值为 {"a", "b", "c", "d"}
    s2.size // 4
  • add(value)

    向 Set 中添加一个值,返回 Set 结构本身,所以可以使用链式调用

    s2.add('e').add('f').add('g')
    // s2 的值为 {"a", "b", "c", "d", "e", "f", "g"}
  • delete(value)
    s2.delete('c')
    // 返回true,表示成功删除
    // s2 的值为 {"a", "b", "d", "e", "f", "g"}
  • has(value)
    s2.has('d')
    // 返回true,表示存在"d"
    s2.has('y')
    // 返回false,表示不存在"y"
  • clear()

    清除所有成员,无返回值

    s2.clear()
    // Set(0) {}

1.2 Set循环

  • keys():返回键名
  • values():返回键值
  • entries():返回所有成员
  • forEach():循环Set实例所有成员
let set = new Set(['red', 'green', 'blue']);
for (let item of set.keys()) {
 console.log(item);
}
// red
// green
// blue

for (let item of set.values()) {
 console.log(item);
}
// red
// green
// blue

for (let item of set.entries()) {
 console.log(item);
}
// ["red", "red"]
// ["green", "green"]
// ["blue", "blue"]

//可以省略values方法,直接用for...of循环遍历Set。
for (let x of set) {
 console.log(x);
}
// red
// green
// blue

1.3 Set应用

(1) 数组去重
let array = [1,2,1,4,5,3,'1'];
[...new Set(array)]     // [1, 2, 4, 5, 3, "1"]
(2) 实现并集、交集、差集
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}

2. WeakSet

WeakSet 结构与 Set 类似,也是不重复的值的集合。

但WeakSet 的成员只能是对象,而不能是其他类型的值

img

2.2 WeakSet的特点

  • WeakSet没有size属性
  • 不能循环,因为内部数据随时可能消失,循环机制无法保证数据存在
  • 使用的WeakSet的优势是使用完后被垃圾回收,减少内存资源浪费。

3. Map

JavaScript的对象 Object 本质上是键值对的集合(Hash结构),但是传统上只能用字符串当作键。这给它的使用带来了很大的限制。

为了解决这个问题,ES6提供了Map数据结构。它类似于对象,也是键值对的集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。

img

const m1 = new Map()
const k = {a:3}

m1.set(k, 'mapValue')  // { {a:3} => "mapValue"}, 对象也能档 key,真太便利啦
m1.get(k)   // mapValue

Map 还可以接受一个数组作为参数,这个数组的成员是一个个表示键值对的数组

const m2 = new Map([
    ['name', '大彬哥'],
    ['age', 18]
])
// {'name'=>'大彬哥', 'age'=>18}

3.1 Map属性及操作方法

  • size
    const m2 = new Map([
        ['name', '大彬哥'],
        ['age', 18]
    ])
    m2.size // 2
  • set(key, value)、get(key)

    set设置一个键名为 key 键值为 value 的成员,并返回整个 Map 结构,如果已经存在该键名,则会更新键值

    get读取这个 key 对应的值,如果没有则返回 undefined

    m2.set('sex', 'boy')
    // {"name" => "大彬哥", "age" => 18, "sex" => "boy"}
    m2.set('name', '涂涂')
    // {"name" => "涂涂", "age" => 18, "sex" => "boy"}
    
    m2.get('sex')
    // "boy"
  • has(key) 、 delete(key) 、clear()
    m2.has('age')  // true
    m2.delete('age')  // true , 
    // m2 变成了 {"name" => "涂涂", "sex" => "boy"}
    m2.clear()
    // m2 变成了 Map(0) {}

3.2 Map循环

Map实例的循环方式和Set类似,可以用 keys、values、entries、forEach 等方式循环成员

const m2 = new Map([
    ['name', '大彬哥'],
    ['age', 18]
])
for (let key of m2.keys()) {console.log(key)}
// name
// age

for (let value of m2. values()) {console.log(value)}
// 大彬哥
// 18

for (let item of m2. entries()) {console.log(item[0], item[1])}
// name 大彬哥
// age 18
// 这里的 item 是一个数组,其中第一个值为键名,第二个值为键值

m2.forEach((value, key) => console.log(key,value))
// name 大彬哥
// age 18

3.3 Map应用

  • Map 转为 Array,使用扩展运算符 ...
let m_1 = new Map([[1, 'name'], ['name', 'js']]);
[...m_1];  // 返回值为 [[1,"name"],["name","js"]]
  • Array 转为 Map
let arr = [[1, 12], [1, 24], ['name', 'ji'], ['name', 'js']];
let arr2m = new Map(arr);
// 返回值为 Map(2) {1 => 24, "name" => "js"}

4. WeakMap

WeakMap结构与Map结构类似,也是用于生成键值对的集合。

不同之处在于,WeakMap 不会阻止它的键值被垃圾回收。那意味着你可以把数据和对象关联起来不用担心内存泄漏。

WeakMap 应用的典型场合就是 DOM 节点作为键名:

var vm = new WeakMap();
var element = document.querySelector('.element');

vm.set(element, "Original");
vm.get(element);    // Original

element.parentNode.removeChild(element);    // 删除节点,系统会回收element这个Dom节点对象
element = null;
vm.get(element);    // undefined, WeakMap自动删除了element这个成员

5. 总结

5.1 Set 与 Map

在使用的过程中明显的Set和Map比我们之前经常使用的Array和Object是有明显的便捷优势的。

如果对数据结构存储的唯一性有要求,考虑使用Set。

如果数据的复杂程度高,考虑使用Map,在一些构建工具中是非常喜欢使用Map这种数据结构来进行配置,因为map是一种灵活、高效性、适合一对一查找的数据结构。

5.2 WeakMap 与 WeakSet

相比于 Map 与 Set 的强引用,弱引用可以令对象在 “适当” 情况下正确被垃圾回收,减少内存资源浪费。