ChatGPT解决这个技术问题 Extra ChatGPT

检查值是否是 JavaScript 中的对象

你如何检查一个值是否是 JavaScript 中的一个对象?

变量是变量。它可以指一个对象。此外,您可能想要定义“对象” - 正如答案和评论所示,存在各种相互冲突的定义(例如 null 是否是对象)。
OP,IMO,您应该接受@Daan 的答案,因为它是最好的解决方案,并且应该列在其他答案之上,以便首先看到它。 (无意冒犯其他也有很好答案的人。)
恕我直言,这实际上取决于您(寻求此问题答案的人)对对象的看法,以及您检查它的原因。如果您试图将数组(即对象)与其他对象区分开来,或者如果您试图将标量值与“向量”分开,这个问题会给出不同的答案。并且是否应排除 null(根据 typeof 是一个对象)或函数(即对象),这实际上取决于您检查它的原因。这就是为什么有这么多答案,其中大多数在上下文中是正确的。
如果您可以先说出“是一个对象”的确切含义,那就太好了。 (或者,明确地说,您正在寻求的部分答案是确定“是一个对象”的各种流行含义,然后区分它们。)缺乏这一点,每个人都在互相交谈。
@tiffon 如何在 stackoverflow.com/a/52478680/1096194 给出一个中肯的答案。当我看到许多投票率最高的答案中的细节长度不知所措时,我写了这篇文章。我相信它应该得到更多的关注。

N
Naetmul

如果是 typeof yourVariable === 'object',它是一个对象或 null

如果您想排除 null、数组或函数,只需:

if (
    typeof yourVariable === 'object' &&
    !Array.isArray(yourVariable) &&
    yourVariable !== null
) {
    executeSomeCode();
}


函数也是对象,应包含在您的检查中。
在这种情况下,yourVariable !== null 会是更好的做法吗?
@RightSaidFred 似乎 typeof null == 'object' 不会在 ES6 中修复。他们说:This proposal has been rejected. It was implemented in V8 but it turned out that it broke a lot of existing sites. In the spirit of One JavaScript this is not feasible.
@Tresdin 最好的方法是运行 Object.prototype.toString.call(yourVar),作为您需要检查的 yourVar。如果是数组,Object.prototype.toString.call([1,2]) 返回 [object Array]
被否决是因为数组也被视为对象,因此您还应该选中 Array.isArray(yourVariable)
r
rap-2-h

更新:

此答案不完整,并提供误导性结果。例如,null 在 JavaScript 中也被认为是 object 类型,更不用说其他几种边缘情况了。遵循以下建议,然后转到其他 "most upvoted (and correct!) answer"

typeof yourVariable === 'object' && yourVariable !== null

原答案:

尝试使用 typeof(var) 和/或 var instanceof something

编辑:这个答案给出了如何检查变量属性的想法,但它不是一个防弹配方(毕竟根本没有配方!)用于检查它是否是一个远离它的对象。由于人们倾向于在不做任何研究的情况下从这里寻找要复制的东西,我强烈建议他们转向另一个,最受支持(和正确!)的答案。


这个答案是不正确的。 typeof 为 null 返回“object”,它不是对象,并且 instanceof 不适用于使用 Object.create(null) 创建的对象。
typeof null...object
数组也将作为“对象”返回,如:someArray instanceof Object //truetypeof someArray === 'object' // true。如果您尝试检测数组,那么:Object.prototype.toString.call(someObject) === "[object Object]""[object Array]" 怎么样?
@Jonathan,有更好的理由拒绝我的回答,您是否有军事背景? :)
这不应该是公认的答案。除了乔纳森提出的文体问题之外,它根本不正确,并且没有在例如@matt-fenwick 的回答中提出非常重要的微妙之处。
S
Safin Ghoghabori

让我们在 Javascript 中定义“对象”。根据 MDN docs,每个值要么是对象,要么是原语:

原始,原始值 不是对象且没有任何方法的数据。 JavaScript 有 7 种原始数据类型:string、number、bigint、boolean、undefined、symbol 和 null。

什么是原始人?

3

'ABC'

真的

无效的

不明确的

什么是对象(即不是原语)?

对象.原型

一切都源自 Object.prototype Function.prototype Object Function function C(){} -- 用户自定义函数 C.prototype -- 用户自定义函数的原型属性:这不是 Cs 原型 new C() -- " new"-ing 一个用户定义的函数 Math Array.prototype arrays {"a": 1, "b": 2} -- 使用文字符号创建的对象 new Number(3) -- 原语的包装器......许多其他的东西...

Function.prototype Object Function function C(){} -- 用户自定义函数

目的

功能

function C(){} -- 用户定义的函数

C.prototype -- 用户定义函数的原型属性:这不是 Cs 原型 new C() -- "new"-ing 用户定义函数

new C() -- "new"-ing 一个用户定义的函数

数学

Array.prototype 数组

数组

{"a": 1, "b": 2} -- 使用文字符号创建的对象

new Number(3) -- 原语的包装器

...许多其他事情...

对象.create(null)

一切都源于 Object.create(null)

如何检查一个值是否是一个对象

instanceof 本身不起作用,因为它错过了两种情况:

// oops:  isObject(Object.prototype) -> false
// oops:  isObject(Object.create(null)) -> false
function isObject(val) {
    return val instanceof Object; 
}

typeof x === 'object' 不起作用,因为误报 (null) 和误报(函数):

// oops: isObject(Object) -> false
function isObject(val) {
    return (typeof val === 'object');
}

Object.prototype.toString.call 不起作用,因为所有原语都存在误报:

> Object.prototype.toString.call(3)
"[object Number]"

> Object.prototype.toString.call(new Number(3))
"[object Number]"

所以我使用:

function isObject(val) {
    if (val === null) { return false;}
    return ( (typeof val === 'function') || (typeof val === 'object') );
}

@Daan 的回答似乎也有效:

function isObject(obj) {
  return obj === Object(obj);
}

因为,根据 MDN docs

Object 构造函数为给定值创建一个对象包装器。如果值为 null 或未定义,它将创建并返回一个空对象,否则,它将返回一个与给定值对应的类型的对象。如果该值已经是一个对象,它将返回该值。

第三种似乎可行的方法(不确定它是否为 100%)是使用 Object.getPrototypeOf which throws an exception 如果其参数不是对象:

// these 5 examples throw exceptions
Object.getPrototypeOf(null)
Object.getPrototypeOf(undefined)
Object.getPrototypeOf(3)
Object.getPrototypeOf('abc')
Object.getPrototypeOf(true)

// these 5 examples don't throw exceptions
Object.getPrototypeOf(Object)
Object.getPrototypeOf(Object.prototype)
Object.getPrototypeOf(Object.create(null))
Object.getPrototypeOf([])
Object.getPrototypeOf({})

obj === Object(obj) 为数组返回 true
var x = []; console.log(x === Object(x)); // return true
正如我在回答中提到的,@Illuminator 数组是 Javascript 中的对象。
getPrototypeOf 不适用于例如已撤销的代理,这些代理是对象但会抛出。
为什么不 ({}).toString.apply(obj) === '[object Object]' 这区分数组和不是数组的对象
G
Gust van de Wal

underscore.js 提供了以下方法来确定某物是否真的是一个对象:

_.isObject = function(obj) {
  return obj === Object(obj);
};

更新

由于 V8 中的先前错误和较小的微速度优化,该方法从 underscore.js 1.7.0(2014 年 8 月)开始如下所示:

_.isObject = function(obj) {
  var type = typeof obj;
  return type === 'function' || type === 'object' && !!obj;
};

在 javascript 中,数组也是一个对象,所以大多数时候你想排除数组:return obj === Object(obj) && Object.prototype.toString.call(obj) !== '[object Array]'
为什么要排除数组?它们是成熟的对象。
因为大多数时候您想将 {} 与 [] 区分开来,例如作为函数中的输入
@Nickolai ..and 用于迭代嵌套对象。
很好的答案。也处理 null。应该是公认的答案。
I
Ionică Bizău

Object.prototype.toString.call(myVar) 将返回:

"[object Object]" 如果 myVar 是一个对象

"[object Array]" 如果 myVar 是一个数组

等等

有关这方面的更多信息以及为什么它是 typeof 的良好替代品,check out this article


我最近了解到typeof [] === 'object' --> true。这就是你需要的这个方法。
@Christophe 不区分原语和对象Object.prototype.toString.call(3) -> "[object Number]"Object.prototype.toString.call(new Number(3)) -> "[object Number]"
@MattFenwick我不认为这是OP试图识别的那种“对象”
@Christophe 你为什么这么认为?恕我直言,在 OP 没有为“对象”给出任何其他定义的情况下,对我来说,使用在整个 ECS 规范中一致使用的定义似乎是最合理的。
getType=function(obj){return Object.prototype.toString.call(obj).match(/\[object (\w+)\]/)[1];};
L
Leto

用于简单地检查对象或数组而无需额外的函数调用(速度)。还发布了 here

是数组()

isArray = function(a) {
    return (!!a) && (a.constructor === Array);
};
console.log(isArray(        )); // false
console.log(isArray(    null)); // false
console.log(isArray(    true)); // false
console.log(isArray(       1)); // false
console.log(isArray(   'str')); // false
console.log(isArray(      {})); // false
console.log(isArray(new Date)); // false
console.log(isArray(      [])); // true

isLiteralObject() - 注意:仅用于 Object 字面量,因为它为自定义对象返回 false,例如 new Date 或 new YourCustomObject。

isLiteralObject = function(a) {
    return (!!a) && (a.constructor === Object);
};
console.log(isLiteralObject(        )); // false
console.log(isLiteralObject(    null)); // false
console.log(isLiteralObject(    true)); // false
console.log(isLiteralObject(       1)); // false
console.log(isLiteralObject(   'str')); // false
console.log(isLiteralObject(      [])); // false
console.log(isLiteralObject(new Date)); // false
console.log(isLiteralObject(      {})); // true

@zupa: !!a 做什么?
@3000 好吧,如果我们省略 (!!a) 部分它会崩溃,因为 null 和 undefined 没有构造函数。 (!!a) 过滤掉它们。这是否回答你的问题?
@zupa @3000 Boolean(a) 更长,但更直观。只是不要使用 new Boolean(a): (here's why)!
令人惊讶的是,最佳答案在页面下方。这基本上回答了这个问题——这是否会在 JSON 中表示为以 { 字符开头的东西。对于数组的情况,只要不需要支持IE < 9、你可以使用Array.isArray()来判断某个东西是否是一个数组。它通过了您提供的所有测试用例。
@BradKent 没有双重否定 !!a isObject(null) 将返回 null 而不是 false
2
2540625

我喜欢简单的:

function isObject (item) {
  return (typeof item === "object" && !Array.isArray(item) && item !== null);
}

如果该项目是一个 JS 对象,并且它不是一个 JS 数组,并且它不是 null……如果这三个都为真,则返回 true。如果三个条件中的任何一个失败,&& 测试将短路并返回 false。如果需要,可以省略 null 测试(取决于您如何使用 null)。

文档:

http://devdocs.io/javascript/operators/typeof

http://devdocs.io/javascript/global_objects/object

http://devdocs.io/javascript/global_objects/array/isarray

http://devdocs.io/javascript/global_objects/null


console.log(isObject(new Date())) 怎么样?为什么日期应该是对象而不是数组?
@macher 因为 new Date() 返回一个对象。从逻辑的角度来看,数组不是对象——尽管 JavaScript 会处理和报告它们。然而,在实践中,看到它们相等是没有帮助的,因为它们不是。例如,一个对象没有 length 属性,也没有 push() 之类的方法。有时你可能想给一个函数重载参数,你需要在数组或对象之间做出区别,特别是如果其他参数取决于给定的参数。
@StanE 数组绝对是对象。不知道为什么您认为对象不能具有 length 属性或 push 之类的方法,Object.create(Array.prototype) 是具有这些属性的非数组对象的一个微不足道的反例。数组的特别之处在于它们是具有自定义 [[DefineOwnProperty]] 基本内部方法的奇异对象,但它们仍然是对象。
@Oriol我既没有写过数组不是对象,也没有写过对象不能有 length 属性(我的意思是对象文字默认没有 length 属性)。我写道,从 logical 的角度来看,数组不是对象。我说的是程序逻辑。有时需要检查一个数组是否是“真实”数组,而绝对不是“真实”对象。这就是 Array.isArray() 的用途。想象一下,您有一个接受对象或对象数组的函数。检查特殊属性或方法是一个肮脏的解决方案。原生方式总是更好。
typeof null"object",而不是 "undefined"
c
cn007b

使用函数 Array.isArray:

function isObject(o) {
  return o !== null && typeof o === 'object' && Array.isArray(o) === false;
}

没有函数 Array.isArray:

只是惊讶于错误答案有多少赞 😮
只有 1 answer 通过了我的测试!!!在这里,我创建了我的简化版本:

function isObject(o) {
  return o instanceof Object && o.constructor === Object;
}

至于我,它很清晰,很简单,而且很有效!这是我的测试:

console.log(isObject({}));             // Will return: true
console.log(isObject([]));             // Will return: false
console.log(isObject(null));           // Will return: false
console.log(isObject(/.*/));           // Will return: false
console.log(isObject(function () {})); // Will return: false

再一次:并非所有答案都通过了这个测试!!! 🙈

如果您需要验证该对象是特定类的实例,则必须使用特定类检查构造函数,例如:

function isDate(o) {
  return o instanceof Object && o.constructor === Date;
}

简单测试:

var d = new Date();
console.log(isObject(d)); // Will return: false
console.log(isDate(d));   // Will return: true

结果,您将拥有严格而健壮的代码!

如果您不会创建 isDateisErrorisRegExp 等函数,您可以考虑使用此通用函数的选项:

function isObject(o) {
  return o instanceof Object && typeof o.constructor === 'function';
}

它不适用于前面提到的所有测试用例,但对于所有对象(普通或构造)来说已经足够了。

isObjectObject.create(null) 的情况下不起作用,因为 Object.create 的内部实现已在 here 中解释,但您可以在更复杂的实现中使用 isObject

function isObject(o, strict = true) {
  if (o === null || o === undefined) {
    return false;
  }
  const instanceOfObject = o instanceof Object;
  const typeOfObject = typeof o === 'object';
  const constructorUndefined = o.constructor === undefined;
  const constructorObject = o.constructor === Object;
  const typeOfConstructorObject = typeof o.constructor === 'function';
  let r;
  if (strict === true) {
    r = (instanceOfObject || typeOfObject) && (constructorUndefined || constructorObject);
  } else {
    r = (constructorUndefined || typeOfConstructorObject);
  }
  return r;
};

已经基于此实现创建了 package on npm v1!它适用于所有前面描述的测试用例! 🙂


最佳答案!适用于提到的许多情况here
因为这对 isObject(myDateObject) 返回 false,所以这不是问题的答案。它不告诉变量是否是对象,只有当它是特定类的对象时。这里的问题是针对任何对象返回 true 的通用函数。
@Yetanotherjosh 这确实是一个答案🤓您提到了答案中描述的案例,重点是-您必须将 isDate 用于 yourDateObject 以编写健壮的代码,否则您将拥有脆弱的 isObject 方法。
@VladimirKovpak 在我的评论中使用 Date 是错误的选择,因为是的,答案确实讨论了 Date。但 Date 只是无限可能的类之一,这一点适用于任何其他类。示例:class Foo() { }; var x = new Foo(); isObject(x) 返回 false。我不确切知道 OP 的用例是什么,但很容易设想必须了解所有可能的类专门针对每一个类进行检查的场景 将是不可行的。
@Yetanotherjosh 我已经更新了我的答案。并增加了 1 个案例。
E
Erisan Olasheni

我的天啊!我认为这可能比以往任何时候都短,让我们看看:

短代码和最终代码

function isObject(obj) { return obj != null && obj.constructor.name === "Object" } console.log(isObject({})) // 返回 true console.log(isObject([])) //返回 false console.log(isObject(null)) // 返回 false

解释

返回类型

typeof JavaScript 对象(包括 null)返回 "object"

console.log(typeof null, typeof [], typeof {})

检查他们的构造函数

检查它们的 constructor 属性会返回带有它们名称的函数。

console.log(({}).constructor) // 返回一个名为“Object”的函数 console.log(([]).constructor) // 返回一个名为“Array”的函数 console.log((null). constructor) //抛出错误,因为 null 实际上没有属性

介绍 Function.name

Function.name 返回函数的只读名称或 "anonymous" 用于闭包。

console.log(({}).constructor.name) // 返回“对象” console.log(([]).constructor.name) // 返回“数组” console.log((null).constructor.name) //抛出错误,因为null实际上没有属性

注意:截至 2018 年,Function.name 可能无法在 IE 中使用 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/name#Browser_compatibility


我真的很喜欢这个,简明扼要。据我所知,它只在一件事情上失败。如果 obj = Object.create(null) 以及为什么你会这样做......?
如果您愿意,可以排除这种罕见的情况:return obj != null && obj.constructor && obj.constructor.name === "Object" 条件“obj.constructor”返回 false,因为 Object.create(null) 创建了一个没有属性的对象,甚至没有 .__proto__ 或 .constructor。
根据您的回答,我在 NodeJS 中的最终 (ES11) 助手是:const isObject = (obj) => (obj ?? false)?.constructor?.name === "Object"; 谢谢!
A
Alireza

好的,在回答你的问题之前,让我们先给你这个概念,在 JavaScript 中,函数是 Object,还有 null、Object、Arrays 甚至 Date,所以你看到没有像 typeof obj === 'object' 这样的简单方法,所以上面提到的所有内容都会返回 true,但是有一些方法可以通过编写函数或使用 JavaScript 框架来检查它,OK:

现在,假设您有这个对象是一个真实的对象(不是 null 或函数或数组):

var obj = {obj1: 'obj1', obj2: 'obj2'};

纯 JavaScript:

//that's how it gets checked in angular framework
function isObject(obj) {
  return obj !== null && typeof obj === 'object';
}

或者

//make sure the second object is capitalised 
function isObject(obj) {
   return Object.prototype.toString.call(obj) === '[object Object]';
}

或者

function isObject(obj) {
    return obj.constructor.toString().indexOf("Object") > -1;
}

或者

function isObject(obj) {
    return obj instanceof Object;
}

您可以通过调用它们在代码中简单地使用上述函数之一,如果它是一个对象,它将返回 true:

isObject(obj);

如果你使用的是 JavaScript 框架,他们通常会为你准备好这些类型的函数,这些是其中的几个:

jQuery:

 //It returns 'object' if real Object;
 jQuery.type(obj);

角度:

angular.isObject(obj);

下划线和 Lodash:

//(NOTE: in Underscore and Lodash, functions, arrays return true as well but not null)
_.isObject(obj);

您还想检查它是否不是数组。所以函数 isObject(obj) { return obj !== null && typeof obj === 'object' && !Array.isArray(obj); }
我同意你的观点,但正如你在评论中看到的那样,它是在 angularJs 中完成的,我在函数前面的评论中提到了它,他们将数组视为对象......查看此处了解更多信息:{ 1}
l
last-child

这取决于您对“是一个对象”的含义。如果你想要所有不是原始的东西,即你可以设置新属性的东西,这应该可以解决问题:

function isAnyObject(value) {
    return value != null && (typeof value === 'object' || typeof value === 'function');
}

它不包括原语(纯数字/NaN/Infinity、纯字符串、符号、true/falseundefinednull),但对于其他所有内容(包括 NumberBooleanString 对象)。请注意,JS 没有定义与 typeof 一起使用时应返回的“主机”对象(例如 windowconsole),因此很难用这样的检查来覆盖这些对象。

如果您想知道某物是否是“普通”对象,即它是作为文字 {} 还是使用 Object.create(null) 创建的,您可以这样做:

function isPlainObject(value) {
    if (Object.prototype.toString.call(value) !== '[object Object]') {
        return false;
    } else {
        var prototype = Object.getPrototypeOf(value);
        return prototype === null || prototype === Object.prototype;
    }
}

2018 年编辑:因为 Symbol.toStringTag 现在允许自定义 Object.prototype.toString.call(...) 的输出,所以在某些情况下,上面的 isPlainObject 函数可能会返回 false,即使对象以文字开始其生命。可以说,按照惯例,带有自定义字符串标记的对象不再完全是纯对象,但这进一步混淆了 Javascript 中纯对象的定义。


为什么 typeof === 'function' 被认为是一个对象?函数不是对象,不是吗? “new myFunc()” 将成为一个对象,是的,但是一个普通的函数?
不,每个函数都是 Javascript 中的一个对象,无论它是如何创建的。您可以在它们上设置属性(除非它们被冻结),它们是 instanceof Object,两个相同的函数字面量并不严格相等,它们是通过引用传递的,等等。
H
HalfWebDev

我的上帝,其他答案太混乱了。

简答

typeof anyVar == 'object' && anyVar instanceof Object && !(anyVar instanceof Array)

要对此进行测试,只需在 chrome 控制台中运行以下语句。

情况1。

var anyVar = {};
typeof anyVar == 'object' && anyVar instanceof Object && !(anyVar instanceof Array) // true

案例 2。

anyVar = [];
typeof anyVar == 'object' && anyVar instanceof Object && !(anyVar instanceof Array) // false

案例 3。

anyVar = null;
typeof anyVar == 'object' && anyVar instanceof Object && !(anyVar instanceof Array); // false

解释

好吧,让我们分解一下

typeof anyVar == 'object' 从三个候选者返回 true - [], {} and null

anyVar instanceof Object 将这些候选人缩小到两个 - [], {}

!(anyVar instanceof Array) 缩小到只有一个 - {}

请打鼓!

至此,您可能已经学会了如何在 Javascript 中检查 Array。


值得注意的是,当 anyVar 是一个函数时,这也会返回 false(根据需要)。
很好的答案@HalfWebDev,但是为了满足 Jamie Birch 评论的功能,我们可以做这种 typeof anyVar == 'object' && anyVar instanceof Object && !(anyVar instanceof Array) && typeof anyVar !== 'function'
T
Talha

尝试这个

if (objectName instanceof Object) {
  alert('Not an object');
}
else {
  alert('An object');
}

为什么你会检查布尔值?
这错过了两种情况:Object.prototype instanceof Object ->错误的。 Object.create(null) instanceof Object ->错误的。
日期呢? new Date() instanceof Object =>真的
此代码假设数组作为对象。
O
Oriol

检查值类型的最合理方法是 typeof 运算符。唯一的问题是它被严重破坏了:

它返回 null 的“对象”,它属于 Null 类型。

它为属于 Object 类型的可调用对象返回“函数”。

它可以(几乎)为非标准的不可调用对象返回任何它想要的东西。例如,IE 似乎喜欢“未知”。唯一被禁止的结果是“函数”和原始类型。

typeof 仅对非 null 基元可靠。因此,检查一个值是否为对象的一种方法是确保 typeof 返回的字符串不对应于原语,并且该对象不是 null。然而,问题是未来的标准可能会引入新的原始类型,而我们的代码会将其视为对象。新类型不经常出现,但例如 ECMAScript 6 引入了 Symbol 类型。

因此,我只推荐其结果取决于值是否为对象的方法,而不是 typeof。以下打算成为

测试值是否属于 Object 类型的正确方法的全面但不详尽的列表。

Object 构造器 Object 构造器将传递的参数强制为对象。如果它已经是一个对象,则返回相同的对象。因此,您可以使用它将值强制转换为对象,并严格将该对象与原始值进行比较。以下函数需要 ECMAScript 3,它引入了 ===: function isObject(value) { /* 需要 ECMAScript 3 或更高版本 */ return Object(value) === value;我喜欢这种方法,因为它简单且具有自我描述性,并且类似的检查也适用于布尔值、数字和字符串。但是,请注意,它依赖于不被遮蔽或更改的全局对象。

构造函数 当你实例化一个构造函数时,它可以返回一个与刚刚创建的实例不同的值。但是除非它是一个对象,否则该值将被忽略。以下函数需要 ECMAScript 3,它允许构造函数返回非对象。在 ECMAScript 3 之前抛出错误,但当时不存在 try 语句。 function isObject(value) { /* 需要 ECMAScript 3 或更高版本 */ return new function() { return value; }() === 值;虽然比前面的例子简单一点,但这个例子不依赖于任何全局属性,因此可能是最安全的。

this value 旧的 ECMAScript 规范要求 this 值是一个对象。 ECMAScript 3 引入了 Function.prototype.call,它允许调用具有任意 this 值的函数,但被强制为对象。 ECMAScript 5 引入了一种严格模式来消除这种行为,但在草率模式下,我们仍然可以(但可以说不应该)依赖它。 function isObject(value) { /* 在草率模式下需要 ECMAScript 3 或更高版本 */ return function() { return this === value; }.call(值); }

[[Prototype]] 所有普通对象都有一个称为 [[Prototype]] 的内部槽,其值决定了它从哪个其他对象继承。该值只能是对象或空值。因此,您可以尝试创建一个从所需值继承的对象,并检查它是否有效。 Object.create 和 Object.getPrototypeOf 都需要 ECMAScript 5。 function isObject(value) { /* 需要 ECMAScript 5 或更高版本 */ try { Object.create(value);返回值 !== null; } 捕捉(错误){ 返回错误; } } function isObject(value) { /* 需要 ECMAScript 5 或更高版本 */ function Constructor() {} Constructor.prototype = value;返回 Object.getPrototypeOf(new Constructor()) === 值; }

一些新的 ECMAScript 6 方法 ECMAScript 6 引入了一些新的间接方法来检查值是对象。他们使用之前看到的方法将值传递给一些需要对象的代码,包裹在 try 语句中以捕获错误。一些隐藏的例子,不值一提 function isObject(value) { /* 需要 ECMAScript 6 或更高版本 */ try { Object.setPrototypeOf({}, value);返回值 !== null; } 捕捉(错误){ 返回错误; } } function isObject(value) { /* 需要 ECMAScript 6 或更高版本 */ try { new WeakSet([value]);返回真; } 捕捉(错误){ 返回错误; } }

注意:我有意跳过了一些方法,例如 Object.getPrototypeOf(value) (ES5) 和 Reflect 方法 (ES6),因为它们调用了可能会做一些讨厌的事情的基本内部方法,例如,如果 value 是一个代理。出于安全原因,我的示例仅引用 value 而不直接访问它。


“只有我和大安的答案是完全正确的。”考虑到我完全不同意你的前两句话,这有点冒昧。
@zzzzBov 好吧,我查看了所有答案,但除了我的和 Daan 的答案外,他们并不能确保总是返回正确的答案。我可以为他们中的大多数人提供可重复的反例。其他人建议检查 typeof 是否返回“函数”或“对象”,但正如我所解释的,规范允许某些对象有其他结果。 Matt Fenwick 的答案包含与 Daan 相同的正确答案,但也包含不正确的答案。
我不同意您的答案“完全正确”的前提,认为其他人“不确保始终返回正确答案”并不能以任何方式反驳我的立场。此外,该问题并未就什么输入应该产生什么输出提出任何要求。
@zzzzBov问题询问如何检查某物是否是对象。 ECMAScript 定义了对象是什么,所以我使用该定义。我看不出任何其他合理的解释。做其他事情的答案(如排除数组)在某些情况下可能很有用,但它们不检查某物是否是对象。
E
Emilio Grisolía

有点晚了......对于“普通对象”(我的意思是,像 {'x': 5, 'y': 7})我有这个小片段:

function isPlainObject(o) {
   return (o === null || Array.isArray(o) || typeof o == 'function' || o.constructor === Date ) ?
           false
          :(typeof o == 'object');
}

它生成下一个输出:

console.debug(isPlainObject(isPlainObject)); //function, false
console.debug(isPlainObject({'x': 6, 'y': 16})); //literal object, true
console.debug(isPlainObject(5)); //number, false
console.debug(isPlainObject(undefined)); //undefined, false
console.debug(isPlainObject(null)); //null, false
console.debug(isPlainObject('a')); //string, false
console.debug(isPlainObject([])); //array?, false
console.debug(isPlainObject(true)); //bool, false
console.debug(isPlainObject(false)); //bool, false

它总是对我有用。仅当“o”的类型为“object”但不为 null、数组或函数时,if 才会返回“true”。 :)


如前面的答案所述,如果是 Date 对象,您的方法将失败。
I
Inanc Gumus

准备使用检查功能

function isObject(o) {
  return null != o && 
    typeof o === 'object' && 
    Object.prototype.toString.call(o) === '[object Object]';
}

function isDerivedObject(o) {
  return !isObject(o) && 
    null != o && 
    (typeof o === 'object' || typeof o === 'function') &&
    /^\[object /.test(Object.prototype.toString.call(o));
}

// Loose equality operator (==) is intentionally used to check
// for undefined too

// Also note that, even null is an object, within isDerivedObject
// function we skip that and always return false for null

解释

在 Javascript 中,null、Object、Array、Date 和函数都是对象。虽然, null 有点做作。因此,最好先检查空值,以检测它不是空值。

检查 typeof o === 'object' 保证 o 是一个对象。如果没有这个检查,Object.prototype.toString 将毫无意义,因为它会返回任何东西的对象,即使是 undefined 和 null!例如:toString(undefined) 返回[object Undefined]!在 typeof o === 'object' 检查之后,toString.call(o) 是检查 o 是否为对象、派生对象(如 Array、Date 或函数)的好方法。

在 isDerivedObject 函数中,它检查 o 是否是一个函数。因为,函数也是一个对象,这就是它存在的原因。如果它没有这样做,函数将返回为假。示例:isDerivedObject(function() {}) 将返回 false,但现在它返回 true。

人们总是可以改变什么是对象的定义。因此,可以相应地更改这些功能。

测试

function isObject(o) { return null != o && typeof o === 'object' && Object.prototype.toString.call(o) === '[object Object]'; } function isDerivedObject(o) { return !isObject(o) && null != o && (typeof o === 'object' || typeof o === 'function') && /^\[object /.test(Object .prototype.toString.call(o)); } // 测试 // 是 null 一个对象吗? console.log( '是 null 一个对象吗?', isObject(null) ); console.log( '是 null 一个派生对象吗?', isDerivedObject(null) ); // 1234 是一个对象吗? console.log('1234 是一个对象吗?', isObject(1234) ); console.log( '1234 是派生对象吗?', isDerivedObject(1234) ); // new Number(1234) 是一个对象吗? console.log('new Number(1234) 是一个对象吗?', isObject(new Number(1234)) ); console.log( '新 Number(1234) 是派生对象吗?', isDerivedObject(1234) ); // 函数对象是对象吗? console.log( '是 (new (function (){})) 一个对象吗?', isObject((new (function (){}))) ); console.log( 'is (new (function (){})) 是派生对象吗?', isObject((new (function (){}))) ); // {} 是一个对象吗? console.log('是 {} 一个对象吗?', isObject({}) ); console.log( '是 {} 一个派生对象吗?', isDerivedObject({}) ); // 数组是对象吗? console.log( '数组是对象吗?', isObject([]) ) console.log( '数组是派生对象吗?', isDerivedObject([]) ) // Date 是对象吗? console.log('Date 是一个对象吗?', isObject(new Date())); console.log( 'Date 是派生对象吗?', isDerivedObject(new Date()) ); // 函数是对象吗? console.log( '函数是对象吗?', isObject(function(){}) ); console.log( '函数是派生对象吗?', isDerivedObject(function(){}) );


你好 !很棒的帖子,但即使产生正确的结果也有一个小错字: console.log( 'is (new (function (){})) a derived object?', isObject((new (function (){}))) ) ;
J
Jayant Bhawal

这是一个带有可选链接的答案,也许是这个问题的最小 isObj 函数。

const isObj = o => o?.constructor === Object; // 对于这个 console.log(isObj({})); // 目的! // 这些为 false console.log(isObj(0)); // 数字 console.log(isObj([])); // 数组 console.log(isObj('lol')); // 字符串 console.log(isObj(null)); // null console.log(isObj(undefined)); // 未定义的 console.log(isObj(() => {})); // 函数 console.log(isObj(Object)); // 班级


new Error() 在您的函数中将是错误的。
@TinyRoy 不应该是这样吗?错误实例不是对象。如果我有什么问题,请告诉我。 :)
如果您的意图是排除从 Object 继承的实例,那么您是对的,但我将它们视为对象。它们具有对象的所有属性。
我相信这就是问题所在。否则基本上一切都继承自 Object。
'?" 符号是什么意思?
G
Gust van de Wal

如果您想检查 objectprototype 是否仅来自 Object。过滤掉 StringNumberArrayArguments 等。

function isObject (n) {
  return Object.prototype.toString.call(n) === '[object Object]';
}

或作为单表达式箭头函数 (ES6+)

const isObject = n => Object.prototype.toString.call(n) === '[object Object]'

这是最好的方法,但我会在第二行让它变得更容易:return Object.prototype.toString.call(n) === '[object Object]'
您也可以删除 null 检查,因为 Object.prototype.toString.call(null) === '[object Null]'
K
Kania
var a = [1]
typeof a //"object"
a instanceof Object //true
a instanceof Array //true

var b ={a: 1}
b instanceof Object //true
b instanceof Array //false

var c = null
c instanceof Object //false
c instanceof Array //false

我被要求提供更多细节。检查我们的变量是否为对象的最简洁易懂的方法是 typeof myVar。它返回一个带有类型的字符串(例如"object""undefined")。

不幸的是,Array 和 null 也有一个类型 object。要仅获取真实对象,需要使用 instanceof 运算符检查继承链。它将消除 null,但 Array 在继承链中有 Object。

所以解决方案是:

if (myVar instanceof Object && !(myVar instanceof Array)) {
  // code for objects
}

/./ instanceof Object //true
如果使用最终解决方案,函数将被视为对象
K
Kamil Kiełczewski

表现

今天 2020.09.26 我在 Chrome v85、Safari v13.1.2 和 Firefox v80 上针对所选解决方案在 MacOs HighSierra 10.13.6 上执行测试。

结果

解决方案 C 和 H 在所有情况下在所有浏览器上都是最快/最快的

对于所有情况,解决方案 D 和 G 在所有浏览器上都是最慢/最慢的

https://i.stack.imgur.com/6zkbC.png

细节

我为解决方案执行 3 个测试用例 A B C D E F G H I J K L M N { 15} P Q R S T U V

对于小物体 - 你可以在这里运行它

对于大物体 - 你可以在这里运行它

没有对象 - 你可以在这里运行它

下面的代码片段展示了解决方案之间的差异。 Solutions AG 对 Matt Fenwick 所描述的选定案例给出了正确的答案

// https://stackoverflow.com/a/14706877/860099 函数 A(x) { return x === Object(x); }; // https://stackoverflow.com/a/42250981/860099 函数 B(x) { return _.isObject(x); } // https://stackoverflow.com/a/34864175/860099 function C(x) { return x != null && (typeof x === 'object' || typeof x === 'function'); } // https://stackoverflow.com/a/39187058/860099 function D(x) { return new function() { return x; }() === x; } // https://stackoverflow.com/a/39187058/860099 函数 E(x) { return function() { return this === x; }.call(x); } // https://stackoverflow.com/a/39187058/860099 function F(x) { /* 需要 ECMAScript 5 或更高版本 */ try { Object.create(x);返回 x !== null; } 捕捉(错误){ 返回错误; } } // https://stackoverflow.com/a/39187058/860099 function G(x) { /* 需要 ECMAScript 5 或更高版本 */ function Constructor() {} Constructor.prototype = x;返回 Object.getPrototypeOf(new Constructor()) === x; } // https://stackoverflow.com/a/8511332/860099 function H(x) { return typeof x === 'object' && x !== null } // https://stackoverflow.com/a/ 25715455/860099 函数 I(x) { return (typeof x === "object" && !Array.isArray(x) && x !== null); }; // https://stackoverflow.com/a/22482737/860099 function J(x) { return x instanceof Object; } // https://stackoverflow.com/a/50712057/860099 函数 K(x) { let t= JSON.stringify(x);返回 t ? t[0] === '{' : false; } // https://stackoverflow.com/a/13356338/860099 function L(x) { return Object.prototype.toString.call(x) === "[object Object]"; }; // https://stackoverflow.com/a/46663081/860099 function M(o, strict = true) { if (o === null || o === undefined) { return false; } const instanceOfObject = o instanceof Object; const typeOfObject = typeof o === 'object'; const constructorUndefined = o.constructor === undefined; const constructorObject = o.constructor === Object; const typeOfConstructorObject = typeof o.constructor === 'function';让 r; if (strict === true) { r = (instanceOfObject || typeOfObject) && (constructorUndefined || constructorObject); } else { r = (constructorUndefined || typeOfConstructorObject); } 返回 r; } // https://stackoverflow.com/a/42250981/860099 函数 N(x) { return $.type(x) === 'object'; } // https://stackoverflow.com/a/34864175/860099 函数 O(x) { if (Object.prototype.toString.call(x) !== '[object Object]') { return false; } else { var 原型 = Object.getPrototypeOf(x);返回原型 === null ||原型 === Object.prototype; } } // https://stackoverflow.com/a/57863169/860099 function P(x) { while ( Object.prototype.toString.call(x) === '[object Object]') if ((x = Object.getPrototypeOf(x)) === null) return true return false } // https://stackoverflow.com/a/43289971/860099 function Q(x){ try{ switch(x.constructor){ case Number: case 函数:case 布尔值:case 符号:case 日期:case 字符串:case RegExp:return x.constructor === Object;案例错误:案例EvalError:案例范围错误:案例参考错误:案例语法错误:案例类型错误:案例URIError:返回(对象===错误?错误:x.constructor)===对象;案例数组:案例Int8Array:案例Uint8Array:案例Uint8ClampedArray:案例Int16Array:案例Uint16Array:案例Int32Array:案例Uint32Array:案例Float32Array:案例Float64Array:返回(对象===数组?数组:x.constructor)===对象;案例对象:默认:返回(对象===对象?对象:x.constructor)===对象; } } catch(ex){ return x == Object; } } // https://stackoverflow.com/a/52478680/860099 function R(x) { return typeof x == 'object' && x instanceof Object && !(x instanceof Array); } // https://stackoverflow.com/a/51458052/860099 function S(x) { return x != null && x.constructor?.name === "Object" } // https://stackoverflow.com /a/42250981/860099 函数 T(x) { return x?.constructor?.toString().indexOf("Object") > -1; } // https://stackoverflow.com/a/43223661/860099 function U(x) { return x?.constructor === Object; } // https://stackoverflow.com/a/46663081/860099 function V(x) { return x instanceof Object && x.constructor === Object; } // ------------- // 测试 // ------------- console.log('column: 1 2 3 4 5 6 - 7 8 9 10 11'); [A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V] .map(f= > console.log(`${f.name}: ${1*f(new Date())} ${1*f(/./)} ${1*f({})} ${1* f(Object.prototype)} ${1*f(Object.create(null))} ${1*f(()=>{})} - ${1*f("abc")} ${1 *f(3)} ${1*f(true)} ${1*f(null)} ${1*f(undefined)}`)) console.log(` 列图例(测试用例):1: new Date() 2: /./ (RegExp) 3: {} 4: Object.prototype 5: Object.create(null) 6: ()=>{} (function) 7: "abc" (string) 8: 3 (number) 9: true (boolean) 10: null 11: undefined Rows: 1 = is object 0 = is NOT object 理论上第 1-6 列应该有 1,第 7-11 列应该有 0 `);