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相反。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,110评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,443评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,474评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,881评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,902评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,698评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,418评论 3 419
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,332评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,796评论 1 316
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,968评论 3 337
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,110评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,792评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,455评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,003评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,130评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,348评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,047评论 2 355

推荐阅读更多精彩内容