ECMAScript 6:WeakSet 有什么用?

新手上路,请多包涵

WeakSet 应该通过弱引用存储元素。也就是说,如果一个对象没有被其他任何东西引用,它应该从 WeakSet 中清除。

我写了以下测试:

 var weakset = new WeakSet(),
    numbers = [1, 2, 3];

weakset.add(numbers);
weakset.add({name: "Charlie"});

console.log(weakset);

numbers = undefined;

console.log(weakset);

即使我的 [1, 2, 3] 数组没有被任何东西引用,它也没有从 WeakSet 中删除。控制台打印:

 WeakSet {[1, 2, 3], Object {name: "Charlie"}}
WeakSet {[1, 2, 3], Object {name: "Charlie"}}

这是为什么?

另外,我还有一个问题。直接将对象添加到 WeakSets 有什么意义,就像这样:

 weakset.add({name: "Charlie"});

那些是 Traceur 的故障还是我遗漏了什么?

最后,如果我们甚至无法遍历它也无法获取当前大小,那么 WeakSet 的实际用途是什么?

原文由 Robo Robok 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 325
2 个回答

它不会从 WeakSet 中删除。这是为什么?

很可能是因为垃圾收集器尚未运行。但是,您说您正在使用 Traceur,所以可能只是它们没有得到适当的支持。我想知道 console 如何显示 WeakSet 的内容。

直接将对象添加到 WeakSets 有什么意义?

绝对没有必要将对象文字添加到 WeakSet s。

如果我们甚至无法遍历它也无法获取当前大小,那么 WeakSet 的实际用途是什么?

您所能得到的只是一点信息:集合中是否包含对象(或一般值)?

这在您想要“标记”对象而不实际改变它们(在它们上设置属性)的情况下很有用。许多算法包含某种“如果 x 已经看到”条件( JSON.stringify 循环检测可能是一个很好的例子),当你使用用户提供的值时使用 Set / WeakSet 是可取的。 a WeakSet 的优点是它的内容可以在你的算法仍在运行时被垃圾收集,所以当你处理大量数据时它有助于减少内存消耗(甚至防止泄漏)是懒惰地(甚至可能是异步地)产生的。

原文由 Bergi 发布,翻译遵循 CC BY-SA 3.0 许可协议

这是一个非常难的问题。老实说,我对 JavaScript 的上下文一无所知, 所以我在 esdiscuss 中提问,并从 Domenic 那里得到了令人信服的答案。

出于 安全验证 原因,WeakSets 很有用。如果你希望能够隔离一段 JavaScript。它们允许您 标记 一个对象以指示它属于一组特殊的对象。

假设我有一堂课 ApiRequest

 class ApiRequest {
  constructor() {
    // bring object to a consistent state, use platform code you have no direct access to
  }

  makeRequest() {
    // do work
  }
}

现在,我正在编写一个 JavaScript 平台 - 我的平台允许您运行 JavaScript 来进行调用 - 进行这些调用您需要 ApiRequest - 我只希望您进行 ApiRequest s使用我给你的物品,这样你就无法绕过我设置的任何限制。

然而,目前没有什么能阻止你做:

 ApiRequest.prototype.makeRequest.call(null, args); // make request as function
Object.create(ApiRequest.prototype).makeRequest(); // no initialization
function Foo(){}; Foo.prototype = ApiRequest.prototype; new Foo().makeRequest(); // no super

依此类推,请注意您不能保留 ApiRequest 对象的正常列表或数组,因为这会阻止它们被垃圾收集。除了关闭之外,任何事情都可以通过公共方法实现,例如 Object.getOwnPropertyNamesObject.getOwnSymbols 。所以你和我一起做:

 const requests = new WeakSet();
class ApiRequest {
  constructor() {
    requests.add(this);
  }

  makeRequest() {
    if(!request.has(this)) throw new Error("Invalid access");
    // do work
  }
}

现在,无论我做什么——我必须持有一个有效的 ApiRequest 对象来调用 makeRequest 方法。如果没有 WeakMap/WeakSet,这是不可能的。

所以简而言之, WeakMaps 对于用 JavaScript 编写平台很有用。通常这种验证是在 C++ 端完成的,但添加这些功能将能够在 JavaScript 中移动和制作东西。

(当然,所有 a WeakSet 执行 WeakMap 将值映射到 true 的所有内容也可以为真,但 map 那是

(就像 Bergi 的回答所暗示的那样,从来没有理由将对象文字直接添加到 WeakMapWeakSet

原文由 Benjamin Gruenbaum 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题