有什么方法可以可靠地确定 JavaScript 对象是否是外来对象类型,如果是,它的类型是什么?
通过“异国情调”,我的意思是(就这个问题而言)任何无法使用Object.create
. 这包括ES2016 规范定义为奇异的所有内容(任何“没有一个或多个基本内部方法的默认行为的对象”)以及由ObjectCreate规范方法创建的具有非空internalSlotsList的任何内容,以及任何类型的宿主对象。
通过“可靠”,我的意思是不会被对象添加/删除属性、使用Object.create
或Object.setPrototypeOf
赋予对象意外原型、修改对象的@@toStringTag 或构造函数的@@hasInstance 所欺骗。这对于需要正确处理任意用户数据的库函数很重要。
(这尤其意味着,instanceof
andObject.prototype.isPrototypeOf()
没有用。例如:var a = Object.create(Array.prototype)
制作一个看起来和闻起来像数组的东西——<code>a instanceof Array === true 并且a.push
按a.pop
预期工作——但缺乏神奇的行为.length
并且是很容易证明它不是一个真正的数组异国情调:Array.isArray(a) === false
。)
通过“类型”,我的意思大致是 ECMAScript 5.1 语言规范所指的 [[Class]] - 即,将具有特殊 [[DefineOwnProperty]] 行为的 Array 实例与普通对象分开的质量。
例子
有些情况很简单:
- 可以使用
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 的方法仍然有用。