JavaScript 系列 - Map 和 WeakMap
Map
Map 对象保存键值对,并且能够记住键的原始插入顺序。任何值(对象或者基本类型)都可以作为一个键或一个值。
使用
new Map([iterable])
特点
- 在映射中用作键和值的对象及其他“集合”类型,在自己的内容或属性被修改时仍然保持不变
- 内存地址不一样视为不同 key
- 0、-0 相同
- NaN 相同
- Map 实例会维护键值对的插入顺序,因此可以根据插入顺序执行迭代操作
静态属性
Map[Symbol.species]
访问器属性会返回一个 Map
构造函数
class MyMap extends Map {
// 重写覆盖 MyMap species to the parent Map constructor
static get [Symbol.species]() {
return Map;
}
}
实例属性
Map.prototype.size
实例方法
-
Map.prototype.set(key, value)
- 返回的是当前的 Map 对象
- 链式调用
-
Map.prototype.get(key)
如果找不到
key
,返回undefined
-
Map.prototype.has(key)
返回一个布尔值
-
Map.prototype.delete(key)
返回 true。如果删除失败,返回 false
-
Map.prototype.clear()
没有返回值
-
Map.prototype[@@iterator]()
const map1 = new Map(); map1.set('0', 'foo'); map1.set(1, 'bar'); const iterator1 = map1[Symbol.iterator](); for (const item of iterator1) { console.log(item); } // Expected output: Array ["0", "foo"] // Expected output: Array [1, "bar"]
-
遍历
Map.prototype.keys()
Map.prototype.values()
Map.prototype.entries()
Map.prototype.forEach(value, key)
- 默认迭代器
map[Symbol.iterator] === map.entries
借用数组方法
new Map([...map].filter())
new Map([...map].map())
转换
-
Map
转为数组[...myMap]
-
数组转为
Map
new Map([])
-
Map
转为对象- 都是字符串,它可以无损地转为对象
- 有非字符串的键名,那么这个键名会被转成字符串,再作为对象的键名
- 遍历
Map
然后赋值给object
function strMapToObj(strMap) { let obj = Object.create(null); for (let [k, v] of strMap) { obj[k] = v; } return obj; }
-
对象转为
Map
Object.entries
let obj = { a: 1, b: 2 }; let map = new Map(Object.entries(obj)); function objToStrMap(obj) { let strMap = new Map(); for (let k of Object.keys(obj)) { strMap.set(k, obj[k]); } return strMap; }
-
Map
转为JSON
Map
的键名都是字符串,这时可以选择转为对象JSON
function strMapToJson(strMap) { return JSON.stringify(strMapToObj(strMap)); }
Map
的键名有非字符串,这时可以选择转为JSON
数组
function mapToArrayJson(map) { return JSON.stringify([...map]); }
-
JSON
转为Map
- 所有键名都是字符串
function jsonToStrMap(jsonStr) { return objToStrMap(JSON.parse(jsonStr)); }
- 整个
JSON
就是一个数组,且每个数组成员本身,又是一个有两个成员的数组
function jsonToMap(jsonStr) { return new Map(JSON.parse(jsonStr)); }
使用场景
- 内存占用 Map
- 插入性能 Map
- 查找速度 Object
- 删除性能 Map
Map 和 Object
- 如果键在运行时才能知道,或者所有的键类型相同,所有的值类型相同,那就使用
Map
- 如果需要将原始值存储为键,则使用
Map
- 如果需要对个别元素进行操作,使用
Object
意外的键
- Map 默认情况不包含任何键。只包含显式插入的键
- 一个 Object 有一个原型,原型链上的键名有可能和你自己在对象上的设置的键名产生冲突
键的类型
- 一个 Map 的键可以是任意值,包括函数、对象或任意基本类型
- 一个 Object 的键必须是一个 String 或是 Symbol
键的顺序
- Map 中的键是有序的。因此,当迭代的时候,一个 Map 对象以插入的顺序返回键值
- 虽然 Object 的键目前是有序的,但并不总是这样,而且这个顺序是复杂的。因此,最好不要依赖属性的顺序
Size
- Map 的键值对个数可以轻易地通过 size 属性获取
- Object 的键值对个数只能手动计算
迭代
- Map 是可迭代的的,所以可以直接被迭代
- Object 没有实现迭代协议,所以使用 JavaSctipt 的 for...of 表达式并不能直接迭代对象
性能
- 在频繁增删键值对的场景下表现更好
- 在频繁添加和删除键值对的场景下未作出优化
序列化和解析
- Map 没有元素的序列化和解析的支持
- 原生的由 Object 到 JSON 的序列化支持,使用 JSON.stringify(),原生的由 JSON 到 Object 的解析支持,使用 JSON.parse()
WeakMap
WeakMap 对象是一组键/值对的集合,其中的键是弱引用的。其键必须是对象,而值可以是任意的。
实例方法
WeakMap.prototype.delete(key)
WeakMap.prototype.get(key)
WeakMap.prototype.has(key)
WeakMap.prototype.set(key, value)
特点
- 只接受对象作为键名(null除外),不接受其他类型的值作为键名
- 键名所指向的对象,不计入垃圾回收机制
- 不能遍历操作
用途
DOM 节点作为键名
const m = new WeakMap();
const loginButton = document.querySelector("#login");
// Associates some metadata with the node
m.set(loginButton, { disabled: false });
loginButton.addEventListener(
"click",
function () {
m.set(loginButton, { disabled: true });
},
false
);
部署私有属性
const User = (() => {
const wm = new WeakMap();
class User {
constructor(id) {
this.idProperty = Symbol("id");
this.setId(id);
}
setPrivate(property, value) {
const privateMembers = wm.get(this) || {};
privateMembers[property] = value;
wm.set(this, privateMembers);
}
getPrivate(property) {
return wm.get(this)[property];
}
setId(id) {
this.setPrivate(this.idProperty, id);
}
getId(id) {
return this.getPrivate(this.idProperty);
}
}
return User;
})();
const user = new User(123);
alert(user.getId()); // 123
user.setId(456);
alert(user.getId()); // 456
这篇好文章是转载于:学新通技术网
- 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
- 本站站名: 学新通技术网
- 本文地址: /boutique/detail/tanhfheehc
系列文章
更多
同类精品
更多
-
TypeScript接口、type关键字可读、只读属性、继承接口|类、规范类、函数|可索引|类|混合类型接口、ReadonlyArray、接口和amp;type、映射类型
-
typescript 使用 setTimeout 返回值类型 eslint 检查错误 ‘NodeJS‘ is not defined.eslintno-undef
-
antd ERROR in ./node_modules/antd/lib/button/style/index.less javascriptEnabled
-
typescript---配置类相关内容(十五)
-
TSTypeScript泛型 T 的用法
-
使用回调函数作为参数的函数改造为返回 Promise 的具体例子
-
photoshop保存的图片太大微信发不了怎么办
PHP中文网 06-15 -
《学习通》视频自动暂停处理方法
HelloWorld317 07-05 -
Android 11 保存文件到外部存储,并分享文件
Luke 10-12 -
word里面弄一个表格后上面的标题会跑到下面怎么办
PHP中文网 06-20 -
photoshop扩展功能面板显示灰色怎么办
PHP中文网 06-14 -
微信公众号没有声音提示怎么办
PHP中文网 03-31 -
excel下划线不显示怎么办
PHP中文网 06-23 -
excel打印预览压线压字怎么办
PHP中文网 06-22 -
怎样阻止微信小程序自动打开
PHP中文网 06-13 -
TikTok加速器哪个好免费的TK加速器推荐
TK小达人 10-01