“异国情调”,我的意思是(为了这个问题的目的)任何使用Object.create
无法创建的东西。这包括所有the ES2016 spec defines as exotic(任何“没有一个或多个基本内部方法的默认行为的对象”)以及ObjectCreate规范方法使用非空创建的任何内容internalSlotsList ,以及任何类型的主机对象。
“可靠”,我的意思是不会被添加/删除对象的属性所欺骗,使用Object.create
或Object.setPrototypeOf
给对象一个意外的原型,修改对象的@@ toStringTag ,或构造函数的@@ hasInstance。这对于需要正确处理任意用户数据的库函数非常重要。
(这尤其意味着,instanceof
和Object.prototype.isPrototypeOf()
没有用处。例如:var a = Object.create(Array.prototype)
制作的内容看起来像一个数组 - a instanceof Array === true
并且a.push
和a.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特有的方法仍然有用。
答案 0 :(得分:0)
但有没有办法检测函数是绑定函数,本机函数还是闭包?
没有。它们都是简单明了的功能。
通过仔细应用原型对象中的方法,可以可靠地检测到其他一些奇特的物体,例如
可以通过调用Set.prototype.has.apply(s,undefined)来检测集合,并查看它是否抛出TypeError。
您可以使用instanceof
运算符来测试对象是否是特定函数构造函数的实例(或其原型链中的某些内容)。
var mySet = new Set();
console.log(mySet instanceof Set);