WeakMap学习思考- Map、WeakMap、强引用 、弱引用和垃圾回收

WeakMap学习思考

Map

Map的问题在于
A map API could be implemented in JavaScript with two arrays (one for keys, one for values) shared by the four API methods. Setting elements on this map would involve pushing a key and value onto the end of each of those arrays simultaneously. As a result, the indices of the key and value would correspond to both arrays. Getting values from the map would involve iterating through all keys to find a match, then using the index of this match to retrieve the corresponding value from the array of values.

Map api共用了两个数组(一个存放key,一个存放value)。给Map set值时会同时将key和value添加到这两个数组的末尾。从而使得key和value的索引在两个数组中相对应。当从Map取值时,需要遍历所有的key,然后使用索引从存储值的数组中检索出相应的value。

Such an implementation would have two main inconveniences:

The first one is an O(n) set and search (n being the number of keys in the map) since both operations must iterate through the list of keys to find a matching value.
The second inconvenience is a memory leak because the arrays ensure that references to each key and each value are maintained indefinitely. These references prevent the keys from being garbage collected, even if there are no other references to the object. This would also prevent the corresponding values from being garbage collected.

这个实现有两个主要缺点,首先是赋值和搜索的时间复杂度为O(n),因为每个操作都需要遍历整个key数组去找到索引和对应的value值;
其次是可能导致内存溢出,因为数组会一直保存每个键值引用,即便是引用早已离开作用域,垃圾回收器也无法回收这些内存。

那么WeakMap 呢

By contrast, native WeakMaps hold “weak” references to key objects As such native WeakMaps do not prevent garbage collection, which eventually removes references to the key object. “Weak” references also avoid preventing garbage collection of values in the map. WeakMaps can be particularly useful constructs when mapping keys to information about the key that is valuable only if the key has not been garbage collected.

到这里就看不懂了 有几个问题:
1.什么情况下会引起垃圾回收,
2.什么叫强引用 弱引用
3.为什么数组会一直保存每个键值引用,就不能垃圾回收了
4.native WeakMaps hold “weak” references to key objects这句话什么意思,
5.为什么弱引用就可以进行垃圾回收了?

1.什么情况下会引起垃圾回收

没有对象在引用该对象了。该对象就会被垃圾回收。转载
从JS中的内存管理说起 —— JS中的弱引用

 var o = { 
  a: {
    b:2
  }
}; 
// 两个对象被创建,一个(b)作为另一个(a)的属性被引用,另一个(a)被分配给变量o
// 很显然,没有一个可以被垃圾收集
var o2 = o; 
// o2变量是第二个对“这个对象”的引用
o = 1;     
 // 现在,“这个对象”只有一个o2变量的引用了,“这个对象”的原始引用o已经没有
var oa = o2.a; 
// 引用“这个对象”的a属性
 // 现在,“这个对象”有两个引用了,一个是o2,一个是oa
o2 = "yo"; 
// 虽然最初的对象现在已经是零引用了,可以被垃圾回收了
// 但是它的属性a的对象还在被oa引用,所以还不能回收
oa = null; 
// a属性的那个对象现在也是零引用
// 它可以被垃圾回收了

这里对 o =1 但 o2 还在引用对象做一个解释。按说o2 = o o2和o是指向同一个内存地址的,改变o,o2也会变,但其实这是混淆了
引用类型重新赋值和修改属性的差异

var test = [{ a: 1 }, { b: 2 }]
var part = test[0]
//如果 情况是直接赋值 开辟新的内存地址
part = { a: 2 }
console.log(test, part) 
//[ { a: 1 }, { b: 2 } ]  { a: 2 } test并不会被影响

//如果 情况是修改属性
 part.a = 2
 //[ { a: 2 }, { b: 2 } ] { a: 2 } test 会被影响

//如果,情况是想要赋值 但保留引用
part = Object.assign(part, { a: 2 })
//[ { a: 2 }, { b: 2 } ] { a: 2 } test 会被影响
 

好回到正题,所以如果没有引用指向该对象(零引用),对象将被垃圾回收机制回收。

2.什么叫强引用 弱引用

强引用就是一个小孩A牵着一条狗,他们之间通过狗链儿连着

弱引用就是,旁边有个小孩B指着A牵的狗,说:嘿,那有条狗,B指向那条狗,但他们之间没有是指绑在一起的东西

当A放开狗链,狗就会跑掉(被垃圾回收),无论B是不是还指着

但是,当B不再指着那条狗,狗还被A牵着,不会影响它是否跑掉
强引用

var obj = new Object(); 

一般我们创建一个对象,都是建立一个强引用。只有 obj= null才会被回收。
弱引用

var obj = new WeakObject();

我们什么都不用做,只用静静的等待垃圾回收机制执行,obj 所引用的对象就会被回收。

3.为什么数组会一直保存每个键值引用,就不能垃圾回收了

ES6 系列之 WeakMap

const key = new Array(5 * 1024 * 1024);
const arr = [
[key, 1]
];

arr建立了对 [[key, 1]](代号Obj)的强引用,即使key= null,也只是解除了
只是去掉了 key 对 Obj 的强引用,并没有去除 arr 对 Obj 的强引用,所以 Obj 还是不会被回收掉, key也就不会被回收掉。同理 Map

let map = new Map()
let key = new Array[5*1024*1024]
//建立了 arr 对key所引用对象的强引用
let arr = map.set(key, 1)
//不会导致 key 的原引用对象被回收
key  = null

想要被垃圾回收
let map = new Map();
let key = new Array(5 * 1024 * 1024);
map.set(key, 1);
map.delete(key);
key = null;

4.native WeakMaps hold “weak” references to key objects这句话什么意思

ES6之WeakMap
weakmap持有对key所引用对象的弱引用
WeakMap的polyfill

var WeakMap = function() {
    this.name = '__wm__' + uuid()
};

WeakMap.prototype = {
    set: function(key, value) {
       / /Object.defineProperty(obj, prop, desc)
        Object.defineProperty(key, this.name, {
            value: [key, value],
        });
        return this;
    },
    get: function(key) {
        var entry = key[this.name];
        return entry && (entry[0] === key ? entry[1] : undefined);
    },
    ...
};

有什么作用呢 就是这里如果key=null那么就可以直接回收了
ES6 系列之 WeakMap

const wm = new WeakMap();
let key = new Array(5 * 1024 * 1024);
wm.set(key, 1);
key = null;

当我们设置 wm.set(key, 1) 时,其实建立了 wm 对 key 所引用的对象的弱引用,但因为 let key = new Array(5 * 1024 * 1024) 建立了 key 对所引用对象的强引用,被引用的对象并不会被回收,但是当我们设置 key = null 的时候,就只有 wm 对所引用对象的弱引用,下次垃圾回收机制执行的时候,该引用对象就会被回收掉。

5.为什么弱引用就可以进行垃圾回收了

JavaScript中弱引用和强引用的区别
通过JavaScript垃圾回收机制来理解WeakSet/WeakMap中对象的弱引用
基本还是将应用的和垃圾回收机制的 但是没有讲为什么弱引用就可以进行垃圾回收了
WeakMap这种结构有助于防止内存泄漏,一旦消除对键的引用,它占用的内存就会被垃圾回收机制释放。WeakMap 保存的这个键值对,也会自动消失。包括WeakSet也是类似的,内部存储的都是弱引用对象,不会被计入垃圾回收。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值