作者:狐狸家的鱼

GitHub:surRimn

整理自MDN文档

带键的集合

映射

Map对象

一个Map对象在迭代时会根据对象中元素的插入顺序来进行 — 一个 for...of 循环在每次迭代后会返回一个形式为[key,value]的数组。

1、语法
new Map([iterable])

iterable可以是一个数组或者其他iterable对象,其元素或为键值对,或为两个元素的数值。每个键值对都添加到新的Mapnull会被当作undefined

2、属性
  • Map.length:属性length的值为0
  • get Map[@@species]:构造函数用于创建派生对象
  • Map.prototype:表示Map构造器的原型,允许添加属性从而用于所有的Map对象
3、键的相等

键的比较是基于 "SameValueZero" 算法:NaN 是与 NaN 相等的(虽然 NaN !== NaN),剩下所有其它的值是根据 === 运算符的结果判断是否相等。+0 和-0是相同的值。

4、Object 和 Map的比较

Object会被用于将字符串类型映射到数值。Object允许设置键值对、根据键获取值、删除键、检测某个键是否存在

  • Object的键只能是字符串或者 Symbols,在Map里键可以是任意类型,包括函数、对象、基本类型;

  • 必须手动计算Object的尺寸,但是可以使用.size获取使用Map的尺寸

  • Map的遍历遵循元素的插入顺序

  • Map 可直接进行迭代,而 Object 的迭代需要先获取它的键数组,然后再进行迭代

  • Object有原型,所以映射中有一些缺省的键。(可以用 map = Object.create(null) 回避

  • Map 在涉及频繁增删键值对的场景下会有性能优势

这三条提示可以帮你决定用Map还是Object

  • 如果键在运行时才能知道,或者所有的键类型相同,所有的值类型相同,那就使用Map

  • 如果需要将原始值存储为键,则使用Map,因为Object将每个键视为字符串,不管它是一个数字值、布尔值还是任何其他原始值

  • 如果需要对个别元素进行操作,使用Object

5、Map实例

所有的 Map 对象实例都会继承 Map.prototype

(1)属性
  • Map.prototype.constructor:返回一个函数,它创建了实例的原型,默认是Map函数

  • Map.prototype.size:返回Map对象的键/值对的数量

(2)方法
方法 功能
Map.prototype.clear() 移除Map对象的所有键/值对
Map.prototype.delete(key) 如果 Map 对象中存在该元素,则移除它并返回 true;否则如果该元素不存在则返回 false
Map.prototype.get(key) 返回键对应的值,如果不存在,则返回undefined
Map.prototype.has(key) 返回一个布尔值,表示Map实例是否包含键对应的值
Map.prototype.set(key) 设置Map对象中键的值。返回该Map对象
Map.prototype.keys() 返回一个新的 Iterator对象, 它按插入顺序包含了Map对象中每个元素的
Map.rpototype.values() 返回一个新的Iterator对象,它按插入顺序包含了Map对象中每个元素的
Map.prototype.entries() 返回一个新的 Iterator 对象,它按插入顺序包含了Map对象中每个元素的 [key, value]**数组**
Map.prototype.forEach(callbackFn[, thisArg]) 按插入顺序,为 Map对象里的每一键值对调用一次callbackFn函数。如果为forEach提供了thisArg,它将在每次回调中作为this值
Map.prototype[@@interator]() 返回一个新的Iterator对象,它按插入顺序包含了Map对象中每个元素的 [key, value]**数组**
(3)示例

使用Map对象

let sayings = new Map();
sayings.set('dog', 'woof');
sayings.set('cat', "meow");
sayings.set('elephant', 'toot');
console.log(sayings.size);//

sayings.has('fox');
sayings.get('dog');
sayings.delete('dog');
sayings.has('dog');

for (let [key, value] of sayings) {
console.log(key + " goes " + value);
}

sayings.clear();
console.log(sayings.size);//

//打印台信息:
3
cat goes meow
elephant goes toot
0

NaN 作为 Map 的键

NaN 也可以作为Map对象的键。虽然 NaN 和任何值甚至和自己都不相等(NaN !== NaN 返回true)

//将NaN作为Map的键
let myMap = new Map();
myMap.set(NaN, "not a number");
console.log(myMap.get(NaN));//not a number
let otherNaN = Number("foo");
console.log(myMap.get(otherNaN));//not a number

迭代Map

//for..of迭代
for (let [key, value] of sayings) console.log(key + " goes " + value);
for (let key of sayings.keys()) console.log(key);
for (let value of sayings.values()) console.log(value);
for (let [key, value] of sayings.entries()) console.log(key + " goes " + value);

//打印台信息:
cat goes meow
elephant goes toot
cat
elephant
meow
toot
cat goes meow
elephant goes toot

//forEach()迭代
sayings.forEach((value, key) => {
console.log(key + " goes " + value);
}, sayings)

//打印台信息:
cat goes meow
elephant goes toot

Map与数组的关系

let arr = [
["key1", "value1"],
["key2", "value2"]
]
//使用Map构造函数将一个二维键值对数组转换成一个Map对象
let newMap = new Map(arr);
console.log(newMap.get("key1"));
//使用Array.from函数将一个Map对象转换成一个二维键值对数组
console.log(Array.from(newMap));
//在键或值的迭代器上使用Array.from,得到只含有键或值的数组
console.log(Array.from(newMap.keys()))

//打印台信息:
value1
[ [ 'key1', 'value1' ], [ 'key2', 'value2' ] ]
[ 'key1', 'key2' ]

复制或合并Maps

Map能像数组一样被复制

let original = new Map([
[1, 'one']
])
let clone = new Map(original);
console.log(clone.get(1));//one
console.log(original === clone);//false

PS:数据本身未被克隆。

Map对象间可以进行合并,但是会保持键的唯一性。

合并两个Map对象时,如果有重复的键值,则后面的会覆盖前面的。 展开运算符本质上是将Map对象转换成数组。

let first = new Map([
[1, 'one'],
[2, 'two'],
[3, 'three'],
]);

let second = new Map([
[1, 'uno'],
[2, 'dos']
]);

// 合并两个Map对象时,如果有重复的键值,则后面的会覆盖前面的。
// 展开运算符本质上是将Map对象转换成数组。
let merged = new Map([...first, ...second]);

console.log(merged.get(1)); // uno
console.log(merged.get(2)); // dos
console.log(merged.get(3)); // three

集合

Set对象

Set对象是一组不重复的值的集合,可以按照添加顺序来遍历。Set中的元素只会出现一次,即 Set 中的元素是唯一的。

1、语法
new Set([iterable])

如果传递一个可迭代对象,它的所有元素将不重复地被添加到新的 Set中。如果不指定此参数或其值为null,则新的 Set为空。

返回值为一个新的Set对象。

2、值的相等

对于 Set s, +0 (+0 严格相等于-0)和-0是不同的值。NaNundefined都可以被存储在Set 中, NaN之间被视为相同的值(尽管 NaN !== NaN

3、属性
  • Set.lengthlength属性的值为0

  • get Set[@@species]:构造函数用来创建派生对象

  • Set.prototype:表示Set构造器的原型,允许向所有Set对象添加新的属性

4、Set实例
(1)属性
  • Set.prototype.constructor:返回实例的构造函数,默认是Set

  • Set.prototype.size:返回Set对象的键/值对的数量

(2)方法
方法 功能
Set.prototype.clear() 移除Set对象内的所有元素
Set.prototype.delete(key) 移除Set的中与这个值相等的元素,返回Set.prototype.has(value)在这个操作前会返回的值(即如果该元素存在,返回true,否则返回false)。``Set.prototype.has(value)在此后会返回false
Set.prototype.add(key) Set对象尾部添加一个元素。返回该``Set对象
Set.prototype.has(key) 返回一个布尔值,表示该值在Set中存在与否
Set.prototype.keys() values()方法相同,返回一个新的迭代器对象,该对象包含Set对象中的按插入顺序排列的所有元素的值
Set.rpototype.values() 返回一个新的迭代器对象,该对象包含Set对象中的按插入顺序排列的所有元素的值
Set.prototype.entries() 返回一个新的迭代器对象,该对象包含Set对象中的按插入顺序排列的所有元素的值的[value, value]数组。为了使这个方法Map对象保持相似, 每个值的键和值相等
Set.prototype.forEach(callbackFn[, thisArg]) 按照插入顺序,为Set对象中的每一个值调用一次callBackFn。如果提供了thisArg参数,回调中的this会是这个参数
Set.prototype[@@interator]() 返回一个新的Iterator对象,它按插入顺序包含了Set对象中每个元素的 [key, value]**数组**
(3)示例

使用Set对象

let set = new Set();
set.add(1);
set.add("some text");
set.add("foo");
console.log(set.size);
console.log(set.has(1));
set.delete("foo");
for (let item of set) {
console.log(item);
}

//打印台信息:
3
true

迭代Set

//迭代
for (let item of set) console.log(item);
for (let item of set.keys()) console.log(item);
for (let item of set.values()) console.log(item);
for (let [key, value] of set.entries()) console.log(key);
// 用forEach迭代
set.forEach(function (value) {
console.log(value);
});

//打印台信息:
1
some text
1
some text
1
some text
1
some text
1
some text

数组和集合的转换

使用Array.from或者展开操作符来完成集合到数组的转换。Set的构造器接受数组作为参数,可以完成从ArraySet的转换。Set`对象中的值不重复,所以数组转换为集合时,所有重复值将会被删除。

console.log(Array.from(set));//集合转换为数组
console.log([...set]); //用...(展开操作符)操作符将Set转换为Array
set = new Set([1, 2, 3, 4])//集合接收数组作为参数
console.log(set);

//打印台信息:
[ 1, 'some text' ]
[ 1, 'some text' ]
Set { 1, 2, 3, 4 }

String相关

const text = 'China';
set = new Set(text);
console.log(set);
console.log(set.size);

//打印台信息:
Set { 'C', 'h', 'i', 'n', 'a' }
5

数组去重

const num = [2, 3, 4, 4, 2, 4, 5];
console.log([...new Set(num)]);
//打印台信息:
[ 2, 3, 4, 5 ]
5、Array和Set的对比

在JavaScript中使用数组来存储一组元素,而新的集合对象有这些优势:

  • 数组中用于判断元素是否存在的indexOf 函数效率低下

  • Set对象允许根据值删除元素,而数组中必须使用基于下标的 splice 方法

  • 数组的indexOf方法无法找到NaN

  • Set对象存储不重复的值,所以不需要手动处理包含重复值的情况

重学JavaScript - 映射与集合的更多相关文章

  1. 复习 Array,重学 JavaScript

    1 数组与对象 在 JavaScript 中,一个对象的键只能有两种类型:string 和 symbol.下文只考虑键为字符串的情况. 1.1 创建对象 在创建对象时,若对象的键为数字,或者由 字母+ ...

  2. 重学JavaScript - 数组

    作者:狐狸家的鱼 GitHub:surRimn 整理自MDN文档 数组 数组是一种类列表对象,长度和元素类型不固定. 描述 访问数组 JavaScript数组的索引是从0开始的,第一个元素的索引为0, ...

  3. 2.重学javascript 对象和数组

    什么是对象,其实就是一种类型,即引用类型. 一.创建Object类型有两种. ①使用new运算符 <script type="text/javascript"> var ...

  4. 1.重学javascript (一)

    一.script标签解析 <script>xxx</script>这组标签,是用于在html 页面中插入js的主要方法.它主要有以下 几个属性: 1.charset:可选.表示 ...

  5. 【重学Java】Set集合

    Set集合 Set集合概述和特点[应用] 无序不可重复 没有索引,不能使用普通for循环遍历.可以使用迭代器或者增强foreach语句遍历 TreeSet集合 TreeSet集合概述和特点[应用] 无 ...

  6. 重学JavaScript之面向对象的程序设计(继承)

    1. 继承 ES 中只支持实现继承,而且其实现继承主要依靠原型链来实现的. 2. 原型链 ES中 描述了 原型链的概念,并将原型链作为实现继承的主要方法.其基本思想是利用原型让一个引用类型继承另一个引 ...

  7. 重学JavaScript之匿名函数

    1. 什么是匿名函数? 匿名函数就是没有名字的函数,有时候也称为< 拉姆达函数>.匿名函数是一种强大的令人难以置信的工具.如下: function a(a1, a2, a3) { // 函 ...

  8. 重学js之JavaScript 面向对象的程序设计(创建对象)

    注意: 本文章为 <重学js之JavaScript高级程序设计>系列第五章[JavaScript引用类型]. 关于<重学js之JavaScript高级程序设计>是重新回顾js基 ...

  9. 《零基础学JavaScript(全彩版)》学习笔记

    <零基础学JavaScript(全彩版)>学习笔记 二〇一九年二月九日星期六0时9分 前期: 刚刚学完<零基础学HTML5+CSS3(全彩版)>,准备开始学习JavaScrip ...

随机推荐

  1. windows下zookeeper单机版安装+dubbo-admin安装注意点

    一:zookeeper安装 安转包下载地址:http://www.apache.org/dyn/closer.cgi/zookeeper 复制修改conf下的zoo_sample.cfg为zoo.cf ...

  2. springBoot 连接数据库

    心得:1.先添加依赖. 2.在application.yml文件中创建mybatis的连接,与项目连接起来. 3.application.yml文件中可以自行配置服务器的端口,配置mybatis的路径 ...

  3. Linux的cat命令详解

    The cat command reads one or more files and copies them to standard output 也就是说,cat命令读取文件,并显示在 stand ...

  4. Linux中Hard link和Symbol link的区别

    Hard link Hard link不能指向不在同一磁盘的文件 Hard link不能指向目录 Hard link与源文件几乎没有区别.只能通过ls -li看出link关系.另外,删除源文件后,Ha ...

  5. 纯JSP简单登录实例

    记一下,免得以后忘记了,又要去查. 文件共有四个web.xml.login.jsp.logout.jsp.welcome.jsp四个文件 测试环境:Tomcat 6.0.x 假设项目名称是LoginS ...

  6. 回炉Spring--Bean生命周期及AOP

    Spring容器: 在基于Spring的应用中,你的应用对象生存于Spring容器(container)中,Spring容器负责创建对象,装配它们,配置它们并管理它们的整个生命周期,从生存到死亡.(在 ...

  7. Python操作 Memcache

    Memcached Memcached 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载.它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提高动态.数据 库驱动网站的速 ...

  8. LINUX 文件合并,去重

    (1)两个文件的交集,并集前提条件:每个文件中不得有重复行1. 取出两个文件的并集(重复的行只保留一份)cat file1 file2 | sort | uniq > file32. 取出两个文 ...

  9. 慕课-tooltip提示框总结

    在慕课上学Waynej老师的tooltip浮动提示框,老师每次讲课都会强调搬砖的流程,这点在上了老师的几节课后宝宝终于体会到了: 分析→设计→编码→优化 分析:分析该功能到底是怎样的,其实就是需求分析 ...

  10. 每天一个linux常用命令--ls 和 -ll 有什么区别?

    一.-ls 和 -ll  有什么区别? 1. ls 命令可以说是linux下最常用的命令之一.ll不是命令,是ls -l的别名相当于windows里的快捷方式.所以"ll"和“ls ...