【问题标题】:Trying to understand the official ES6 spec regarding Symbol.hasInstance试图了解有关 Symbol.hasInstance 的官方 ES6 规范
【发布时间】:2016-11-07 23:24:06
【问题描述】:

关于 Symbol.hasInstance writes 的 ECMAScript 2015 官方规范:

这个属性(指 Symbol.hasInstance)是不可写的并且 不可配置以防止可用于全局的篡改 暴露绑定函数的目标函数。

现在,即使是不可写和不可配置的属性也可以用 Object.defineProperty() 覆盖,实际上,如果您尝试覆盖 Symbol.hasInstance 以始终返回 true,那么它会这样做。

我不明白报价。

可能会暴露全局函数的场景是在绑定函数的情况下,当您覆盖目标的 Symbol.hasInstance 以返回 true 时。自然它会返回 false,因为目标将其原型交换到绑定函数上,因此绑定函数不是目标的实例。另外,据我所知,我相信它最终会出现在全局范围内的原因是因为绑定函数没有原型,因此实际上不能成为目标函数的实例,所以如果你强制它作为实例,那么目标的原型强制在 不存在 绑定原型上,最终失败并将目标的 this 置于全局范围内。但是,即使我将它设置为返回 true,我仍然无法让它在全局范围内公开目标。

注意,这是我试图做的事情,以更好地理解 JavaScript 的内部工作原理。在实际应用中,我不想全局公开目标。

我已经尝试了数小时的时间摆弄一系列绑定函数的代码 sn-ps 和 Symbol.hasInstance 返回 true,但无济于事。我无法让它在全球范围内公开目标的功能和数据。如果有人更好地理解这一点,那将不胜感激。我撞到了一堵砖墙。

【问题讨论】:

  • 我猜防篡改工作。
  • 它不能阻止完全篡改。如果使用 Object.defineProperty(),即使 Symbol.hasInstance 不可写,也绝对可以覆盖它。我已经覆盖了很多次。仅将其设置为不可写以防止标准重新分配。
  • 不幸的是,它并没有真正解决我的问题。这是一篇很棒的文章,感谢您指出。
  • 我试图理解规范 sn-p 以便能够完成我正在写的关于知名符号的文章。我相信我理解为什么它最终会出现在全球范围内的理论;但是,无法实现证明它的 sn-p 意味着我无法完成这篇文章(并且可能我的理解存在缺陷)。理论是,由于绑定函数没有原型,因此强制绑定函数的不存在原型成为目标的实例将导致分配失败,从而触发对全局范围的默认分配。

标签: javascript ecmascript-6


【解决方案1】:

让我们澄清一下,您说的是规范的19.2.3.6 部分,即Function.prototype[Symbol.hasInstance] 的规范。

最新版本规范中的文字是:

此属性不可写且不可配置,以防止可用于全局公开绑定函数的目标函数的篡改。

这是说你不能做:

// A malicious library loads here and overrides the function.
(function(){
  Object.defineProperty(Function.prototype, Symbol.hasInstance, {
    value: function(instance){
      const context = this;

      // Here, `this === SomeClass`
    },
  });
}();

// Some library loads here.
(function(){
  function SomeClass(){}

  const BoundClass = SomeClass.bind(null);

  var tmp = {} instanceof BoundClass;
})();

因此,在本例中,如果属性为 configurable: true,则恶意库将能够访问 SomeClass,否则它将是完全私有的并在 IIFE 范围内。

【讨论】:

  • 太棒了。事实上,Object.defineProperty 似乎能够遮蔽但不能覆盖 Symbol.hasInstance。那是我错过的东西,所以非常感谢你向我展示了这一点!我仍然不明白可以完成这个答案的两件事:1)为什么我们特别担心目标函数?我认为这与没有原型的绑定函数有关,但我不确定它是如何在这里发挥作用的。 2)这如何暴露在全球范围内?这绝对是正确的轨道和规范的意图。它正在谈论重新定义 Function.prototype。泰!!
  • 1) 这很令人担忧,因为这种情况可能允许您从您无权访问的范围内访问私有数据。假设您有一个恰好在内部使用.bindinstanceof 的库,通常您无法访问它,但这会让您获得对该函数的引用。 2)它是全局范围,因为任何全局脚本如果不是不可配置的,您都可以重新定义该属性。
  • 所以为了完成你的例子,你会说你的 definePrototype 会返回this吗?同样在重新定义 Function.prototype 之后(假设可以工作),您将如何访问对象的私有范围,即执行此操作的代码是什么样的?
  • 我扩展了我的例子。
  • 我假设它返回true,这就是{}instanceof BoundClass 的方式(以及与此相关的任何内容)。我还假设一旦获取了const context = this,该值就可以访问 IIFE 的私有范围,并且可以在以后访问和使用。谢谢你的详细解答
猜你喜欢
  • 2011-10-16
  • 2022-01-23
  • 1970-01-01
  • 1970-01-01
  • 2019-02-16
  • 1970-01-01
  • 1970-01-01
  • 2013-07-10
相关资源
最近更新 更多