在JavaScript中,有些对象可以包含其他对象。数组,集合,地图和对象是其中的几个。这些对象可以分为两组: Keyed collections(通过键('foo','bar')访问的值)和 indexed collections(通过索引(0、1、2、3,...)访问的值)。
我想编写一个函数来确定传递给它的对象是键集合,索引集合还是两者都不是。
起初,我尝试使用Array.isArray
来确定对象是否被索引,但是对于false
,arguments
和HTMLCollection
的实例,它返回了NodeList
。然后,我尝试检查length
属性,但是返回了String
和Function
的误报。
当然这个问题已经解决了,对吧?
答案 0 :(得分:-1)
我相信我有你的答案。这是我在本网站其他地方写的答案的副本。请让我知道它如何为您工作。
以下是常见的骇客入侵类型,有些问题:
const type = obj => Object.prototype.toString.call(obj);
type("abc");// [object String]
type(123);// [object Number]// What's with all the objects?
type([]);// [object Array]
type({});// [object Object]
type(Object.create(null));// [object Object]
type(-1/0);// [object Number] Not exactly a true number
type(NaN);// [object Number] WTF?
如您所见,它存在一些问题。它总是返回用括号括起来的两种类型,第一种总是“对象”。如果总是返回第一种类型的信息,这将使它无用。其次,它的区别还有些局限。它无法告诉我们是将对象创建为文字(纯文本)还是使用Object.create()创建,该对象在调用时需要关键字“ new”。它也毫不客气地称Infinity和NaN为数字。
我希望分享一种解决所有这些问题的更好的typeof函数。它适用于所有原语,包括符号,异常(错误,未定义,空值和NaN),本机对象和函数的最常见情况(数组,映射,对象,函数,数学,日期,承诺等)以及甚至可以在用户制作的对象(标识为Plain)和DOM元素(标识为HTML)之间进行检测。它应该适用于所有现代和较旧的浏览器。它分为几个功能以使代码更易于使用:
const isDOM = obj => (obj.nodeType && !isPlain(obj)) ? true : false;
const isPlain = obj => obj ? obj.constructor === {}.constructor : false;
const sanString = str => str.replace(/[^a-zA-Z ]/g, "");
const isNaN = obj => (Object.is(obj, NaN) === true) ? true : false;
function objType(obj){
if(obj === undefined) return undefined;
if(obj === Infinity) return Infinity;
if(obj === -Infinity) return -Infinity;
if(isDOM(obj)) return 'HTML';
let str = Object.prototype.toString.call(obj);
if(str === '[object Object]' && isPlain(obj)) return 'Plain';
str = sanString(str).split(' ');
if(str[1] === 'Number' && isNaN(obj)) return NaN;
return str[1];}
}
像这样使用:
objType(null);// Null
objType(undefined);// undefined
objType("abc");// String
objType(123);// Number
objType([]);// Array
objType({});// Plain not [object Object]
objType(Object.create(null));// Object is what we want
objType(document.body);// HTML
objType(-1/0);// -Infinity
objType(NaN);// NaN