年底了“谈个对象”吧

简介: 今天要谈的对象是Map和WeakMap。先对这两个对象进行一个简单的介绍总结:Map 的 key 可以是任何类型的值,Object 的键值只能是 string 和 symbols。Map 实例按照插入的顺序存储数据Map 实例的属性更容易删除WeakMap 相比 Map 提供了更优的垃圾回收机制下面进入正题。

Map 是什么


看下 MDN 解释:


The Map object holds key-value pairs and remembers the original insertion order of the keys. Any value (both objects and primitive values) may be used as either a key or a value.


关键词:键值对、按插入顺序有序排列、键或者值可以为任何类型的数据。

语法


new Map([iterable])


我们再看一下 Map 实例上的属性和方法。



初始化一个 Map 实例:


const map = new Map(); // 空的 Map
map.set(1, "first");
map.get(1); // 'first'
const newMap = new Map([
  [1, "zhangsan"],
  [2, "lisi"]
]);
newMap.get(1); // "zhangsan"
newMap.get(2); // "lisi"


键值


对象里的键值只能为字符串。而 Map 实例如上解释可以为任何类型的数据。


const obj = {};
obj[1] = "one";
obj["1"]; // one
obj[1]; // one
const map = new Map();
map.set(1, "one");
map.set("1", "another one");
// map 包含2组键值对: 1, 'one' 以及 '1', 'another one'


这里再说一下,Map 实例当在比较键名的时候采用 sameValueZero 的规则,有点像严格等于 ===,但又有两个例外:NaN 和 NaN、+0 和-0,Map 认为它们一样。


另外,Map 实例还支持链式调用设置键值对,对象只能一次设置一个键值对:


const map = new Map();
map
  .set(1, "one")
  .set(2, "two")
  .set(3, "three");


删除属性


删除对象上的属性值时会一直返回 true,除非这个属性是

删除一个 Map 上的属性时,如果这个属性存在会返回 true,如果不存在则返回 false。


// 删除对象属性
const obj = {
  name: "zhangsan"
};
delete obj.name; // true
delete obj.age; // true,不存在这个属性同样会返回 true
// 删除Map属性
const map = new Map();
map.set("name", "zhangsan");
map.delete("name"); //  true
map.delete("age"); //  false


如果删除对象上所有的属性呢?或许可以这样:


const obj = { 1: 234 };
obj = {};


但是这样的话,你其实只是把一个新的空对象复制给这个实例,而原先的旧对象并不一定就被删除了(要看垃圾回收机制),如果别的地方对它还有引用,那它就还会一直存在。


for (let key in obj) {
  if (obj.hasOwnProperty(key)) {
    delete obj[key];
  }
}


Map 实例就能很好地处理这个问题:map.clear();


遍历


如开头 MDN 上的解释一样, Map 的遍历更好预测。


const obj = {};
obj[5] = "five";
obj[4] = "four";
Object.entries(obj); // [ ['4', 'four'], ['5', "five"] ]
const map = new Map();
map
  .set(5, "five")
  .set(4, "four")
  .entries(); // [ 5 => "five", 4 => "four" ]


和对象类似,Map 也有 3 种方法用于遍历对象:


  • map.keys() 返回键名组成的数组


  • map.values() 返回键值组成的数组


  • map.entries() 返回包含一组组键值对的可遍历的数组


相互转换


Map 构造函数接收一个数组或者可迭代(iterable)对象,所以对象转 Map 实例的时候我们可以用 Object.entries 方法处理:


const obj = {
  one: 1,
  two: 2
};
const map = new Map(Object.entries(obj));
console.log(map.get("one")); // 1


那么又如何把 Map 实例转成对象呢?还好我们有 Object.fromEntries 方法,用法和 Object.entries 相反:


const map = new Map();
map.set("one", 1);
map.set("two", 2);
const obj = Object.fromEntries(map);
console.log(obj.one); // 1


Map vs WeakMap


WeakMapMap 类似,主要的不同点有两处:


  1. WeakMap 的只接受对象作为键名。


const map = new WeakMap();
map.set(1, 2);
// TypeError: Invalid value used as weak map key
map.set({}, 1);


  1. WeakMap 键名所指向的对象,不计入垃圾回收机制。


let obj = { name: "Matt" }; // object can be accessed
let map = new Map();
map.set(obj, true);
obj = null; // 尽管对象被重写了,但是旧对象依然可以在map里访问到


WeakMap 是怎么处理这种情况的:


let obj = { name: "Matt" };
let weakMap = new WeakMap();
weakMap.set(obj, true);
obj = null; // 重写对象,同时也会在 weakMap 里被删除
// weakMap 现在是空


WeakMap 只有四种方法:get, set, delete, has。 之所以没有 size等属性或者方法,就是因为这个机制, WeakMap 实例的长度可能会随时变化,所以从规则上就禁止去访问 WeakMapsize 属性,自然也不会提供用于遍历的那几个属性了。


总结


从一些共同点以及不同点介绍了对象以及 Map 的特性,希望能帮助到你了解他们的优缺点,进而在适合的场景选用适合的数据结构。


相关文章
|
机器学习/深度学习 人工智能 自然语言处理
从服务内部到实现商业化,美团云所经历的这两年
100 万单、 1000 万单到 1400 万再到 1600 万单的峰值,美团点评的外卖日订单迅速上涨。与此同时,配送体验要求也在不断提升,平台也始终面临运力的挑战,必须不断平衡配送成本和配送体验的要求。
451 0
从服务内部到实现商业化,美团云所经历的这两年
格力电器参与闻泰科技收购半导体,推进500亿“造芯”计划
继成立独立芯片设计公司后,格力电器已经走出了下一步。
585 0
|
机器学习/深度学习 双11 芯片
阿里巴巴开辟科技主航道:内部代号“NASA”
2017年3月9日,阿里巴巴集团在杭州召开首届技术大会,动员全球两万多名科学家和工程师投身“新技术战略”。 会议透露,阿里巴巴正在启动一项代号“NASA”的计划,面向未来20年组建强大的独立研发部门,建立新的机制体制,为服务20亿人的新经济体储备核心科技。
4532 0
|
传感器 人工智能 供应链
“重新定义吹风机器”,物种起源获数百万元天使融资
物种起源自主研发的SYLPH电吹风,在外形上仅一个iphone8的大小,重量只有180g左右,轻巧的外形便于携带。
455 0
马云:心要善,刀要快 | 内部干货
有人说中国公司要开除员工很难,对此有人提出了一个观点叫“心善刀快”,起初听到这个观点的时候,我也被震撼到了,于我而言也是一种教育。后来我们做了一个重要的总结,就是真正要开除员工的时候,要贯彻这个观点——心要善,刀要快。
8359 0