首页 > 解决方案 > 如何确定 JavaScript 对象是键控集合、索引集合还是根本不是集合?

问题描述

在 JavaScript 中,有些对象可以包含其他对象。数组、集合、映射和对象是其中的几个。这些对象可以分为两组: 键控集合(通过键 ('foo', 'bar') 访问的值)和 索引集合(通过索引 (0, 1, 2, 3, ...) 访问的值)。

我想编写一个函数来确定传递给它的对象是键控集合、索引集合还是两者都不是。

起初,我尝试使用Array.isArray来确定对象是否被索引,但这会返回,和false的实例。然后我尝试检查一个属性,但它返回了和的误报。argumentsHTMLCollectionNodeListlengthStringFunction

这个问题肯定已经解决了吧?

标签: javascriptoop

解决方案


我相信我有你的答案。这是我在本网站其他地方写的答案的副本。请让我知道它是如何为您工作的。

以下是一种常见的黑客攻击类型,但有些问题:

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”。它还错误地将无穷大和 NaN 称为数字。

我希望分享一个更好的 typeof 函数来解决所有这些问题。它适用于所有原语,包括符号、异常(错误、未定义、null 和 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

推荐阅读