JavaScript-集合与映射

对象在Javascript编程中经常被用作映射和集合,但是却收到对字符串约束的限制。另外由于对象正常都会继承带名字的属性(如toString)等属性,这些属性也很明显不是为集合和映射准备的。
为此,ES6添加了真正的Set和Map类,接下来进行解析。
代码内的注释 !代表提示 => 模拟控制台输出

一、Set类

什么是集合

集合就是一组值,与数组类似。但与数组不同的是,集合没有索引或顺序,也不允许重复:一个值要么是集合的成员,要么不是;不可能在集合中出现多次

1.1 使用Set()构造函数创建集合对象

let s = new Set(); // ! 创建一个新的空集合,大小(size)为0
let t = new Set([1,s]) // ! 创建一个新的,有两个成员的集合

Set()构造函数的参数必须上一个可迭代的对象(也包括其他的集合)

let str = 'screen'  // ! 创建字符串
let m = new Set(str)  // ! 创建一个新的集合
console.log(m)  // => {'s', 'c', 'r', 'e', 'n'}

1.2 集合不一定要在创建时初始化,也可以使用方法添加或删除元素

先上例子

let s = new Set();  // !创建一个空集合
s.add(2)  // => 添加一个数值
s.add([1,2,3]).add(["a","b","c"]).add("2")  // => 添加两个数组,一个字符串
s.delete([1,2,3])   // => false 集合中包含放是另一个数值
s.delete(2)  // => true 删除成功,集合包含数值2
console.log(s.size) // => 3 集合大小
s.clear()  // => 清空集合

关于这段代码的说明 ↓

  • add(value): 接收一个参数,将参数添加到集合中;如果参数是一个数组,它会把数组添加到集合中,而不是数组元素添加到集合里;add()始终返回调用他的集合。
    如果想添加多个值,可以链缀调用add();例如↓
let s = new Set();
s.add([1,2,3]).add(["a","b","c"]).add(2)
  • delete(value):删除集合中的一个元素,一次只能删除一个。delete返回一个布尔值,指定的值确实是一个集合元素,返回true,反之返回false。
    注意点:集合成员是按照严格相等 === 来判断,集合可以是数值1,也可以是字符串 '1',这两个值不同;如果值是对象(数组、函数)也是 === 来比较。如果想删掉的话,必须传入该“数组”的引用
  • clear(): 清除集合,没有返回值

在实际应用中,使用集合最重要的不是添加或删除元素,而是检查某个值是不是集合成员;使用has()方法。

  • has(value):返回一个布尔值来指示对应的值value是否存在Set对象(集合)中
let s = new Set(['a', 'b'])   // => 创建新集合
console.log(s.has('b'))   // => true 因为有 "b" 这个成员

集合最重要的是它专门为成员测试做了优化,无论集合内有多少成员,has()方法都非常快。(数组的includes()方法也执行成员测试,但执行速度和数组大小相反,因此用数组作为集合比Set对象慢很多)

1.3 Set对象可以迭代,可以使用for...of循环枚举集合所有元素

let arr = [1,2,3]   // => 创建数组
let s = new Set(arr)  // => 创建新集合
for(item of s){
   console.log(item)  // 循环输出 1,2,3
}

1.4 因为Set是可迭代的,所有可以使用···扩展运算符

let arr = [1,2,3]   // => 创建数组
let s = new Set(arr)    // => 创建新集合
console.log(...s)    // => 1 2 3

1.5 因为Set是可迭代的,也有forEach()方法,与数组类似

let arr = [1,2,3]
let s = new Set(arr)    // => 创建新集合
s.forEach(function (item) {
      console.log(item)  // => 1 2 3
})

二、Map类

Map对象表示一组被称为键的值,其中每个键都关联着(或映射到)另一个值。映射类似于数组,只不过他不用连续的整数作为键,而是运行任何值作为索引。于数组类似,映射速度也很快(没有通过索引访问数组那么快)

2.1 通过Map()构造函数创建映射对象,把关联的键和值写成数组的形式

let m = new Map();; // => 创建一个新的空映射
let n = new Map([  // 初始化新映射
     ["one",1],
     ["two",2]
])

Map()构造函数的参数是一个可迭代的对象,包含两个元素的数组[key,value]键值对。正常使用中,通常把关联的键或值写成数组的数组的形式;也可以使用Map()构造函数复制其他映射,或者从已有的对象复制属性名和值:

        let n = new Map([    // 初始化新映射
            ["one",1],
            ["two",2]
        ])
 // ! 也可以使用Map()构造函数复制其他映射
        let copy = new Map(n)  `  // 复制新映射,有和n一样的键和值
        n.delete("one")  
// ! 也可以从已有对象复制属性名和值
        let o = { x:1, y:2 }     // 初始化新对象
        let p = new Map(Object.entries(o))  // => 相当于 new Map([["x",1],["y",2]])
  • set() : 增加、修改;与集合的add()方法类似,可以链缀调用
n.set("there",4) // => 添加映射键“there”和值4
n.set("there",3)  // => 修改映射键“there”和值3
  • get(): 获取;用来查询关联的值
console.log(n.get("there"))  // => 输出与there相关的值
  • has(): 判断里面有没有这个值 true / false
console.log(n.has("name"))  // => false 判断映射是否有键“name”
  • delete() :** 删除指定键**
 n.delete("two")   // ! ["two",2],这个键值对被删除了 
  • clear() : 清除 (慎用,和集合的clear一样)

与集合一样,任何JavaScript值都可以做完映射的键和值,包括null、undefined、NaN以及对象和数组等引用数据类型;也和集合一样,安装全等于 === 而非相等于。

2.2 映射对象是可迭代的,迭代的值上一个或两个元素的数组,可跌带也可以使用...扩展运算符

let n = new Map([   // 初始化新映射
            ["one",1],
            ["two",2]
        ])
        console.log([...n]) // => 输出 
        console.log(...n) // => ['one', 1] (2) ['two', 2]
        console.log(n)  // => {'one' => 1, 'two' => 2}
        for(let [key, value] of n){
            console.log(key, value)
        }

集合和映射都是安装插入的先后顺序迭代的,迭代第一个键值对是最早添加到映射中的,最后一个键值对是最晚添加的。
如果只是想迭代映射的键或关联的值,可以用keys()values()方法。
keys() 取出Map里面所有的键

console.log(n.keys()) // ! 只会单独取出键

values()取出Map里面所有的值

console.log(n.values()) // ! 只会单独取出值

还有一个entries()方法返回所有可迭代对象的键值对
entries() :取出里面所有的键和值 等价于 [...n]

console.log(n.entries())    // ! 全部取出来,和直接打印n差不多,意义不大

2.3 映射同样也实现了forEach()方法

let n = new Map([  // 初始化新映射
            ["one",1],
            ["two",2]
        ])
n.forEach((value,key)=> { 
            console.log(key , value)
        })

注意:是(value,key),与for...of相反。

本文章由javascript技术分享原创和收集

发表评论 (审核通过后显示评论):