如何在JavaScript中可靠地检测奇异物体?

时间:2017-09-18 10:06:54

标签: javascript types specifications language-implementation language-specifications

有没有办法可靠地确定JavaScript对象是否是异类对象类型,如果是,那么它的类型是什么?

“异国情调”,我的意思是(为了这个问题的目的)任何使用Object.create无法创建的东西。这包括所有the ES2016 spec defines as exotic(任何“没有一个或多个基本内部方法的默认行为的对象”)以及ObjectCreate规范方法使用非空创建的任何内容internalSlotsList ,以及任何类型的主机对象。

“可靠”,我的意思是不会被添加/删除对象的属性所欺骗,使用Object.createObject.setPrototypeOf给对象一个意外的原型,修改对象的@@ toStringTag ,或构造函数的@@ hasInstance。这对于需要正确处理任意用户数据的库函数非常重要。

(这尤其意味着,instanceofObject.prototype.isPrototypeOf()没有用处。例如:var a = Object.create(Array.prototype)制作的内容看起来像一个数组 - a instanceof Array === true并且a.pusha.pop按预期工作 - 但缺少神奇的行为.length并且很容易显示不是真正的阵列异域:Array.isArray(a) === false。)

通过“类型”,我的意思大致是指ECMAScript 5.1语言规范所称的[[Class]] - 即,将一个Array实例与其特殊[[DefineOwnProperty]]行为分开的质量来自普通对象

实施例

有些情况很简单:

  • 使用Array.isArray(a)可以可靠地检测阵列异物。
  • 使用typeof f === 'function'可以可靠地检测功能。
    • 但有没有办法检测函数是绑定函数,本机函数还是闭包?
  • 通过从原型对象中仔细应用方法,可以可靠地检测到其他一些奇特的物体。
    • 可以通过调用Set.prototype.has.apply(s, undefined)来检测集合,并查看它是否抛出TypeError。

有没有通用的方法来进行这样的检测?

特别是:

  • 是否有任何一般方法来确定对象是普通的还是异国情调的?
  • 有没有通用的方法来确定异国情调的物体的类型?

我注意到Object.toString.apply(o)以前用于此目的的工作得相当好:尽管在许多浏览器中它都是关于主机对象的类型,对于ES 5.1规范中定义的所有类型,它可以依赖于可靠地告诉您对象是普通的[object Object]还是异国情调的[object <Type>]。但是,在ES6及更高版本中,修改@@toStringTag将颠覆此测试。

在任何符合标准的JS实现中都可以使用的检测方法是理想的,但Node.js特有的方法仍然有用。

1 个答案:

答案 0 :(得分:0)

  

但有没有办法检测函数是绑定函数,本机函数还是闭包?

没有。它们都是简单明了的功能。

  

通过仔细应用原型对象中的方法,可以可靠地检测到其他一些奇特的物体,例如

     

可以通过调用Set.prototype.has.apply(s,undefined)来检测集合,并查看它是否抛出TypeError。

您可以使用instanceof运算符来测试对象是否是特定函数构造函数的实例(或其原型链中的某些内容)。

var mySet = new Set();
console.log(mySet instanceof Set);