百分百源码网-让建站变得如此简单! 登录 注册 签到领金币!

主页 | 如何升级VIP | TAG标签

当前位置: 主页>网站教程>JS教程> 浅谈JavaScript中的Map、WeakMap、Set和WeakSet
分享文章到:

浅谈JavaScript中的Map、WeakMap、Set和WeakSet

发布时间:01/01 来源:未知 浏览: 关键词:

我猜想,超越70%的JavaScript开发人员仅使用对象来收集和保护其项目中的数据。好吧,确实如此,新的汇合对象(例如Map和Set)即便在2015年问世也没有得到充分利用。

因此,今天,我将计议2015年以来的奇妙新功效——MapSetWeakMapWeakSet

阅读此前

  • 这篇文章并不是要告诉你只能用它们。但我见过一些应聘者在编码考试中使用了其中的一种,我喜爱在某些状况下使用它们。由你决议何时在项目中使用它们。
  • 你应当知道什么是可迭代的,以便更好地理解我的计议。

Objects

我们应当第一计议怎样使用对象。

好吧,我信赖90%以上的人已经知道这部分内容了,由于你点击这篇文章是为了理解新的汇合对象,但关于JavaScript的初学者来说,我们还是简便说说它们吧。

const algorithm = { site: "leetcode" };
console.log(algorithm.site); // leetcode

for (const key in algorithm) {
  console.log(key, algorithm[key]);
}

// site leetcode
delete algorithm.site;
console.log(algorithm.site); // undefined

所以我做了一个 algorithm 对象,它的key和value是一个字符串类型的值,而我通过用 . 关键字来调取该值。

别的,for-in 轮回也很适合在对象中轮回。你可以用 [] 关键字拜访其键对应的值。但是不克不及使用 for-of 轮回,由于对象是不成迭代的。

对象的属性可以用 delete 关键字来删除。这样就可以彻底挣脱对象的属性,大家要留意不要和这种办法混淆。

const algorithm = { site: "leetcode" };
// Property is not removed!!
algorithm.site = undefined;
// Property is removed!!
delete algorithm.site;

algorithm.site = undefined 只是将新值分配给 site

好的,我们已经快速计议了有关对象的一些事项:

  • 怎样增加属性
  • 怎样遍历对象
  • 怎样删除属性

Map

Map 是JavaScript中新的汇合对象,其功效相似于对象。但是,与常规对象比拟,存在一些主要差别。

第一,让我们看一个创立Map对象的简便示例。

怎样增加属性

const map = new Map();
// Map(0) {}

Map 不需要创立任何内容,但是增加数据的方式略有不一样。

map.set('name', 'john');
// Map(1) {"name" => "john"}

Map 有一种非凡的办法可在其中增加称为 set 的属性。它有两个参数:键是第一个参数,值是第二个参数。

map.set('phone', 'iPhone');
// Map(2) {"name" => "john", "phone" => "iPhone"}
map.set('phone', 'iPhone');
// Map(2) {"name" => "john", "phone" => "iPhone"}

但是,它不同意你在其中增加现有数据。假如 Map 对象中已经存在与新数据的键对应的值,则不会增加新数据。

map.set('phone', 'Galaxy');
// Map(2) {"name" => "john", "phone" => "Galaxy"}

但是你可以用其他值覆盖现有数据。

怎样遍历对象

Map 是一个可迭代的对象,这意味着可以使用 for-of 语句将其映射。

for (const item of map) {
  console.dir(item);
}
// Array(2) ["name", "john"]
// Array(2) ["phone", "Galaxy"]

要记住的一件事是 Map 以数组情势供给数据,你应当解构数组或拜访每个索引以猎取键或值。

要仅猎取键或值,还有一些办法可供你使用。

map.keys();
// MapIterator {"name", "phone"}
map.values();
// MapIterator {"john", "Galaxy"}
map.entries();
// MapIterator {"name" => "john", "phone" => "Galaxy"}

你乃至可以使用展开操纵符(...)来猎取Map的全部数据,由于展开操纵符还可以在幕后与可迭代对象一起工作。

const simpleSpreadedMap = [...map];
// [Array(2), Array(2)]

怎样删除属性

从 Map 对象中删除数据也很容易,你所需要做的就是调取 delete

map.delete('phone');
// true
map.delete('fake');
// false

delete 返回布尔值,该布尔值指示 delete 函数可否成功删除了数据。假如是,则返回 true,不然返回 false

WeakMap

WeakMap起源于Map,因此它们彼此非常类似。但是,WeakMap具有很大的不一样。

WeakMap的名字是如何来的呢?嗯,是由于它与它的援用链接所指向的数据对象的连接或关系没有Map的连接或关系那么强,所以它是弱的。

那么,这到底是啥意思呢?

差别1:key必需是对象

const John = { name: 'John' };
const weakMap = new WeakMap();
weakMap.set(John, 'student');
// WeakMap {{...} => "student"}
weakMap.set('john', 'student');
// Uncaught TypeError: Invalid value used as weak map key

你可以将任何值作为键传入Map对象,但WeakMap不一样,它只接受一个对象作为键,不然,它将返回一个错误。

差别2:并非Map中的所有办法都支撑

可以使用WeakMap的办法如下。

  • delete
  • get
  • has
  • set

这个话题最大的不一样是WeakMap不支撑迭代对象的办法。但是为什么呢?下面将对此停止描写。

不同3:当GC清算援用时,数据会被删除

与Map比拟,这是最大的不一样。

let John = { major: "math" };

const map = new Map();
const weakMap = new WeakMap();

map.set(John, 'John');
weakMap.set(John, 'John');

John = null;
/* John 被垃圾收集 */

John 对象被垃圾回收时,Map对象将保持援用链接,而WeakMap对象将丧失链接。所以当你使用WeakMap时,你应当思考这个功效。

Set

Set也非常相似于Map,但是Set关于单个值更有用。

怎样增加属性

const set = new Set();

set.add(1);
set.add('john');
set.add(BigInt(10));
// Set(4) {1, "john", 10n}

与Map一样,Set也阻挠我们增加雷同的值。

set.add(5);
// Set(1) {5}

set.add(5);
// Set(1) {5}

怎样遍历对象

由于Set是一个可迭代的对象,因此可以使用 for-offorEach 语句。

for (const val of set) {
  console.dir(val);
}
// 1
// 'John'
// 10n
// 5

set.forEach(val => console.dir(val));
// 1
// 'John'
// 10n
// 5

怎样删除属性

这一部分和 Map 的删除完全一样。假如数据被成功删除,它返回 true,不然返回 false

set.delete(5); 
// true

set.delete(function(){});
// false;

假如你不想将雷同的值增加到数组表单中,则Set大概会非常有用。

/* With Set */
const set = new Set();
set.add(1);
set.add(2);
set.add(2);
set.add(3);
set.add(3);
// Set {1, 2, 3}

// Converting to Array
const arr = [ ...set ];
// [1, 2, 3]

Object.prototype.toString.call(arr);
// [object Array]

/* Without Set */
const hasSameVal = val => ar.some(v === val);
const ar = [];

if (!hasSameVal(1)) ar.push(1);
if (!hasSameVal(2)) ar.push(2);
if (!hasSameVal(3)) ar.push(3);

WeakSet

与WeakMap一样,WeakSet也将丧失对内部数据的拜访链接(假如内部数据已被垃圾收集)。

let John = { major: "math" };

const set = new Set();
const weakSet = new WeakSet();

set.add(John);
// Set {{...}}
weakSet.add(John);
// WeakSet {{...}}

John = null;
/* John 被垃圾收集 */

一旦对象 John 被垃圾回收,WeakSet就没法拜访其援用 John 的数据。并且WeakSet不支撑 for-offorEach,由于它不成迭代。

比力总结

雷同点:增加雷同的值不支撑。

Map vs. WeakMap:WeakMap仅接受对象作为键,而Map不接受。

Map and Set:

  • 可迭代的对象,支撑 for..offorEach... 运算符
  • 离开GC关系

WeakMap and WeakSet:

  • 不是一个可迭代的对象,不克不及轮回。
  • 假如援用数据被垃圾收集,则没法拜访数据。
  • 支撑较少的办法。

结语

不外,我想,许多团队或公司还是没有使用Maps或Sets。或许是由于他们觉得没有必要,或者是由于数组依然可以做到几乎所有他们想要的东西。

然而,在JavaScript中,Maps或Sets大概是非常奇特和强大的东西,这取决于每个状况。所以我但愿有一天,你能有时机使用它们。

原文地址:https://medium.com/better-programming/map-weakmap-set-weakset-in-javascript-77ecb5161e3

作者:Moon

打赏

打赏

取消

感谢您的支持,我会继续努力的!

扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

百分百源码网 建议打赏1~10元,土豪随意,感谢您的阅读!

共有151人阅读,期待你的评论!发表评论
昵称: 网址: 验证码: 点击我更换图片
最新评论

本文标签

广告赞助

能出一分力是一分吧!

订阅获得更多模板

本文标签

广告赞助

订阅获得更多模板