只会用Object?我想推荐你试试Map
当前位置:点晴教程→知识管理交流
→『 技术文档交流 』
导读 在 本文将介绍
为什么这与 可迭代性对象对象的遍历由于对象不能使用使用
1. 会遍历对象所有的可枚举属性,包括原型链上的属性,例如 function Person(name) { this.name = name; } Person.prototype.sayHello = function() { console.log("Hello, I'm " + this.name); }; var obj = new Person("Tom"); for (const prop in obj) { console.log(prop) // name, sayHello } 可以看到 // 方法一:使用hasOwnProperty() for (var prop in obj) { if (obj.hasOwnProperty(prop)) { console.log(prop); // name } } // 方法二:使用Object.keys() var keys = Object.keys(obj); for (var i = 0; i < keys.length; i++) { console.log(keys[i]); // name } 2. 遍历顺序不一定按照对象属性定义的顺序,例如: const obj = { a: 1, b: 2, c: 3, "1": "one", "2": "two", "3": "three" }; for (var key in obj) { console.log(key + ": " + obj[key]); } 这个在谷歌浏览器中会先遍历数字类型的属性,如图: 3. 遍历的索引为字符串类型的数字,并不能直接进行计算,例如 const obj = { 1: "one", 2: "two", 3: "three" }; for (const key in obj) { console.log(key, typeof key); // 1 string; 2 string; 3 string } const arr = [4, 5, 6] for (const index in arr) { console.log(index, typeof index); // 0 string; 1 string; 2 string; } Map如果是 const map1 = new Map(); map1.set('a', 1); map1.set('b', 2); map1.set('c', 3); for (const [key, value] of map1) { console.log(key, value) // a 1; b 2; c 3 } 对于对象,我们还有一个Object.entries() 来做类似的事情,尽管它看起来不是那么流行,但确实可以 const myObject = {a: 1, b: 2, c: 3} for (const [key, value] of Object.entries(myObject)) { console.log(key, value) // // a 1; b 2; c 3 } 对于 // 你可以只便利values,keys for (const value of myMap.values()) { console.log(value) } for (const key of myMap.keys()) { console.log(key) } key内置key当我们这样创建一个对象时: const myMap = {} myMap.valueOf // => [Function: valueOf] myMap.toString // => [Function: toString] myMap.hasOwnProperty // => [Function: hasOwnProperty] myMap.isPrototypeOf // => [Function: isPrototypeOf] myMap.propertyIsEnumerable // => [Function: propertyIsEnumerable] myMap.toLocaleString // => [Function: toLocaleString] myMap.constructor // => [Function: Object] 尽管对象看起来是个空的,你也可以访问这些属性,在MDN中也提到了这个问题: key的顺序
const [[firstKey, firstValue]] = myMap 实现LRU缓存用此特性,我们可以实现一个
class LRUCache { constructor(capacity) { this.capacity = capacity; // 缓存容量 this.map = new Map(); // 使用Map存储键值对 } // 获取键对应的值,如果不存在则返回 -1 get(key) { if (this.map.has(key)) { let value = this.map.get(key); this.map.delete(key); // 删除该键值对 this.map.set(key, value); // 将该键值对重新插入到Map末尾,表示最近使用过 return value; } else { return -1; } } // 设置或更新键和值,如果超过缓存容量,则删除最久未使用的键值对 put(key, value) { if (this.map.has(key)) { this.map.delete(key); } else if (this.map.size >= this.capacity) { // 如果Map中没有该键,且已达到缓存容量上限 let oldestKey = this.map.keys().next().value; // 获取Map中第一个(最久未使用)的键 this.map.delete(oldestKey); } this.map.set(key, value); // 将新的或更新的键值对插入到Map末尾,表示最近使用过 } } key的类型
myMap.set({}, value) myMap.set([], value) myMap.set(document.body, value) myMap.set(function() {}, value) myMap.set(myDog, value) 在 复制与转换复制你可能会觉得对象更容易复制,比如: const copied = {...myObject} const copied = Object.assign({}, myObject) 但,实际上Map也容易复制: js复制代码const copied = new Map(myMap) 同样,你还可以使用structuredClone 深拷贝: const copied = new Map(myMap) 转换// Map转对象 const myObj = Object.fromEntries(myMap) // 对象转Map const myMap = new Map(Object.entries(myObj)) 因此,我们可以不使用元组构造映射,可以将它们构造成对象,这样看起来更加美观: const myMap = new Map([['key', 'value'], ['keyTwo', 'valueTwo']]) // 可以写成 const myMao = new Map(Object.entries({ key: 'value', keyTwo: 'valueTwo' })) 序列化与反序列化
但是,当我们使用时,有个第二个参数传 JSON.stringify(obj, (key, value) => { // Convert maps to plain objects if (value instanceof Map) { return Object.fromEntries(value) } return value }) 我们还可以用相反的方式将对象转回 JSON.parse(string, (key, value) => { if (value && typeof value === 'object') { return new Map(Object.entries(value)) } return value }) 该文章在 2023/10/25 15:18:57 编辑过 |
关键字查询
相关文章
正在查询... |