WeakSet polyfill

909 阅读1分钟

学习了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 实例中