ES6之Set & Map

ES6之前的集合

ES6之前我们能够使用的集合就是Array,其他的集合使用的是Object替代

Set & Map的特点

Set是一个不存在重复元素的集合,一般情况下不是用于遍历每一个元素,通常是监测一个元素是否存在在Set集合中

Map是一个键值对的集合,通常用于缓存频繁取用的数据

Object模拟Set和Map

Object模拟Set

let set = Object.create(null)
set.foo = true

// checking for existence
if (set.foo) {
    // code to execute
}

Object模拟Map

let map = Object.create(null)
map.foo = "bar"

// retrieving a value
let value = map.foo

console.log(value)         // "bar"

Object的问题

Object的key只能是字符串,其他类型的key都会转换成字符串,所以如下例

let map = Object.create(null)
map[5] = "foo"

console.log(map["5"])     // "foo"

当key设置成5的时候,实际上Object会将其转换成字符串"5",所以在Object中key为5和"5"是等价的。同样的,当对象作为key的时候,同样会把对象转换成字符串,如下例

let map = Object.create(null),
      key1 = {},
      key2 = {}
map[key1] = "foo"

console.log(map[key2])     // "foo"

Set

  1. 初始化 -- new
    let set = new Set()
    console.log(set.size)
        
    let set1 = new Set([1,2,3])
    console.log(set.size)
  1. 添加元素 -- add
    let set = new Set()
    set.add(5)
    set.add("5")
    console.log(set.size)

    let set1 = new Set(),
        key1 = {},
        key2 = {}
    set1.add(key1)
    set1.add(key2)
    
    console.log(set1.size)   // 2

这里可以看到,在Set中元素5和"5"是两种不同的元素,同样不同的对象也是不同的元素

Set中不可添加相同的元素

    let set = new Set()
    set.add(5)
    set.add("5")
    set.add(5)     // duplicate - this is ignored
    
    console.log(set.size)    // 2

在Set中判断元素是否重复利用的是 Object.is(),引申阅读

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Equality_comparisons_and_sameness

  1. 判断存在性 -- has
    let set = new Set()
    set.add(5)
    set.add("5")
    
    console.log(set.has(5))    // true
    console.log(set.has(6))    // false    
  1. 删除元素 -- delete & clear
    let set = new Set()
    set.add(5)
    set.add("5")
    console.log(set.has(5)) // true
    
    set.delete(5)
    
    console.log(set.has(5)) // false
    console.log(set.size) // 1
    
    
    set.clear()
    
     
    console.log(set.has("5"))  // false
    console.log(set.size)      // 0
  1. 遍历 -- forEach
    let set = new Set([1, 2])
    
    set.forEach(function(value, key, ownerSet) {
        console.log(key + " " + value)
        console.log(ownerSet === set)
    })

注意:由于set是没有key值的,所以forEach的第一个参数和第二个参数是一样的,都是set中的元素

  1. Set和Array的转化
    let set = new Set([1, 2, 3, 3, 3, 4, 5]),
        array = [...set]
    
    console.log(array)             // [1,2,3,4,5]

场景化:去除数组中重复的元素,对于对象数据没有办法这样处理

思考:对象数组如何去重

Map

  1. Map初始化,设置,获取 -- new set get

示例一:

    let map = new Map()
    map.set("title", "Understanding ECMAScript 6")
    map.set("year", 2016)
    
    console.log(map.get("title"))      // "Understanding ECMAScript 6"
    console.log(map.get("year"))       // 2016

示例二:

    let map = new Map([["name", "Nicholas"], ["age", 25]])
    
    console.log(map.has("name"))  // true
    console.log(map.get("name"))  // "Nicholas"
    console.log(map.has("age"))  // true
    console.log(map.get("age"))  // 25
    console.log(map.size)  // 2
  1. 判断Map中key的存在 -- has
    let map = new Map()
    map.set("title", "Understanding ECMAScript 6")
    map.set("year", 2016)
    console.log(map.has('title'))
  1. 删除元素 -- delete & clear
    let map = new Map()
    map.set('title', 'Understanding ECMAScript 6')
    map.set('year', 2016)
    console.log(map.size)
    
    map.delete('title')
    console.log(map.size)
    
    map.clear()
    console.log(map.size)    
  1. 遍历 -- forEach
    let map = new Map()
    map.set('title', 'Understanding ECMAScript 6')
    map.set('year', 2016)
    map.forEach(function(value, key, ownerMap) {
        console.log(key + ' ' + value)
        console.log(ownerMap === map)
    })
  1. Map与Array之间的转换
    var kvArray = [["key1", "value1"], ["key2", "value2"]]
    
    // 使用常规的Map构造函数可以将一个二维键值对数组转换成一个Map对象
    var myMap = new Map(kvArray)
    
    myMap.get("key1") // 返回值为 "value1"
    
    // 使用Array.from函数可以将一个Map对象转换成一个二维键值对数组
    console.log(Array.from(myMap)) // 输出和kvArray相同的数组
    
    // 或者在键或者值的迭代器上使用Array.from,进而得到只含有键或者值的数组
    console.log(Array.from(myMap.keys())) // 输出 ["key1", "key2"]
  1. 场景

    1.key值不确定的场景

    Map可以接受的key不只有String类型,所以在key值不确定的场景下,使用Map作为优先

    2.元素频繁的新增和删除

    Map是一个纯哈希结构,而Object不是(它拥有自己的内部逻辑)。使用delete对Object的属性进行删除操作存在很多性能问题。所以,针对于存在大量增删操作的场景,使用Map更合适。

WeakSet & WeakMap

具体场景暂无

  1. WeakSet

    • In a WeakSet instance, the add() method, has() method, and delete() method all throw an error when passed a nonobject.

    • Weak sets aren’t iterables and therefore cannot be used in a for-of loop.

    • Weak sets don’t expose any iterators (such as the keys() and values() methods), so there is no way to programmatically determine the con- tents of a weak set.

    • Weak sets don’t have a forEach() method.

    • Weak sets don’t have a size property.

  2. WeakMap

    When you’re deciding whether to use a weak map or a regular map, the primary decision to consider is whether you want to use only object keys. Anytime you’ll be using only object keys, a weak map is the best choice. A weak map will allow you to optimize memory usage and avoid memory leaks by ensuring that extra data isn’t retained after it’s no longer accessible.

    Keep in mind that weak maps give you very little visibility into their con- tents, so you can’t use the forEach() method, the size property, or the clear() method to manage the items. If you need some inspection capabilities, reg- ular maps are a better choice. Just be sure to keep an eye on memory usage.

    Of course, if you only want to use nonobject keys, regular maps are your only choice.

posted @ 2020-03-28 16:45  jie1029  阅读(86)  评论(0编辑  收藏  举报