【问题标题】:Well known Symbols do not work with functions众所周知的符号不适用于函数
【发布时间】:2016-12-25 10:15:46
【问题描述】:

考虑以下两个sn-ps:

obj = {}; // can be [], Number(), eg. but not Function()
obj[Symbol.hasInstance] = () => console.log('89');
({}) instanceof obj;

obj = function() {}; // new Function() too
obj[Symbol.hasInstance] = () => console.log('89');
({}) instanceof obj;

两者都应该记录“89”,但仅在第一个 sn-p 中记录“89”。

在 Chrome 52 中,第一个记录 89,第二个不记录任何内容。

在节点 v6.3.1 中,第一个结果是 TypeError: Expecting a function in instanceof check, but got #<Object>,而第二个没有记录。

这是一个错误吗?预期的行为是什么?在 MDN 上没有任何解释。

【问题讨论】:

  • 规范说 “这个属性是不可写和不可配置的,以防止可用于全局暴露绑定函数的目标函数的篡改。” 但它还说 “构造函数可以通过在函数上公开不同的 @@hasInstance 方法来控制 instanceof 将哪些对象识别为其实例。” ecma-international.org/ecma-262/7.0/… 。根据ecma-international.org/ecma-262/7.0/#sec-instanceofoperator,第一个不应该在 Node.js 中抛出错误。看来 Chrome 是正确的。
  • 但是,@@hasInstance 在原型链中,我实际上并没有改变它,只是在obj 上创建另一个属性@@hasInstancenew Function()function() {} 也是如此,为什么他们的行为不同?
  • 如果一个属性是不可写的,你不能分配给它在链中更高的位置。示例:var a = Object.create(null, {test: {value: 42}}); var b = Object.create(a);b.test = 21; 静默失败。

标签: javascript google-chrome reflection ecmascript-6 symbols


【解决方案1】:

函数的[Symbol.hasInstance]属性不可写且不可配置:

spec 说:

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

因此,作业

obj[Symbol.hasInstance] = () => console.log('89');

静默失败。在 prototype 上定义属性并不重要,如果它不可写,它也不能被“后代”覆盖。

所以 Chrome 的行为是正确的。


对于 Node,它似乎还没有实现 instanceof 的新行为,即它不使用 [Symbol.hasInstance](如果存在)。在这种情况下,正确的操作数必须是一个函数,而第一个示例中的情况并非如此。

【讨论】:

    猜你喜欢
    • 2022-10-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多