重学JavaScript - 映射与集合

作者:狐狸家的鱼

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);//3
​
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);//0
//打印台信息:
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对象存储不重复的值,所以不需要手动处理包含重复值的情况

  •  

 

转载于:https://www.cnblogs.com/suRimn/p/10861689.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值