学习了WeakSet的用法后, 产生了一个疑问,这么神奇的东西能在js层面实现polyfill吗?我们不引用一个对象怎么判断这个对象存在WeakSet实例中呢?上github一搜还真有,而且实现也很简单(polyfill),我们分析一下:
/**
* @module WeakSet
*/
var counter = Date.now() % 1e9;
/**
* @constructor
*/
function WeakSet (data) {
// 生成唯一id, 用于挂载到元素上
this.name = '__st' + (Math.random() * 1e9 >>> 0) + (counter++ + '__');
// Q: 这里无Iterable接口的应报错
data && data.forEach && data.forEach(this.add, this);
};
var proto = WeakSet.prototype;
// 添加原型方法 add, delete, has
proto['add'] = function(val) {
var name = this.name;
// 加上标记
if (!val[name]) Object.defineProperty(val, name, {value: true, writable: true});
return this;
};
proto['delete'] = function(val) {
// 删除就是删除标记
if (!val[this.name]) return false;
val[this.name] = undefined;
return true;
};
// 使用 WeakSet 主要是用这个方法判断某个值是否在 WeakSet 实例中
proto['has'] = function(val) {
// 有标记说明在 WeakSet 实例中
return !!val[this.name];
};
module.exports = WeakSet;
很巧妙的方法,通过给元素加标记,不用引用就能判断某个值是否在 WeakSet 实例中