检查值是否是JavaScript中的对象


1359

如何检查值是否是JavaScript中的Object?


4
变量是变量。它可以引用一个对象。另外,您可能想要定义“对象”-如答案和注释所示,存在各种冲突的定义(例如,是否null为对象)。

8
OP,IMO,您应该接受@Daan的答案,因为它是最好的解决方案,应该在其他答案的上方列出,以便您首先看到它。(对也有好的回答的其他人没有冒犯。)
tiffon 2015年

2
恕我直言,它实际上取决于您(寻求该问题答案的人)对对象的看法以及您为什么检查它。如果试图将数组(即对象)与其他对象区分开来,或者试图将标量值与“向量”分开,此问题给出了不同的答案。而空(即是否一个对象,根据typeof运算)或函数(即对象)应排除与否,实际上取决于你为什么要检查它。这就是为什么答案如此之多,而大多数答案在上下文中都是正确的。
FrancescoMM

const isEmpty =事物=> {typeof事物===“对象”?!!Object.keys(thing).length:!thing && something!== 0};
Mayur S

1
这将是巨大的,如果你能说出究竟是什么开始的“是一个对象”的意思。(或者,明确地说,您要寻找的答案的一部分是弄清楚“是一个对象”的各种流行含义,然后在它们之间进行区分。)缺少这一点,每个人都在互相交谈。
唐·哈奇

Answers:


519

更新

这个答案是不完整的,并且会产生误导性的结果。例如,在JavaScript中null也被视为类型object,更不用说其他几种极端情况了。请遵循以下建议,然后转到其他“最受好评(并且正确!)答案”


原始答案

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

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


208
typeof是运算符,因此不需要()
Yoshi

67
是的,不需要。我只是喜欢这种方式。
Michael Krelin-黑客2011年

150
@ MichaelKrelin-hacker:不幸的是,它使人们感到困惑
RightSaidFred 2011年

11
@RightSaidFred,我对此没有任何解释,但我绝对不愿意在这些表达式中添加额外的括号:)
Michael Krelin-hacker 2011年

117
这个答案是不正确的。typeof返回'object'表示null,这不是对象,并且instanceof不适用于使用创建的对象Object.create(null)
Nikolai 2014年

1630

如果为typeof yourVariable === 'object',则为对象或null。如果要排除null,则使其为null typeof yourVariable === 'object' && yourVariable !== null


31
函数也是对象,应该包含在检查中。
JS_Riddler 2012年

4
在这种情况下会yourVariable !== null更好吗?
hippietrail

9
@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.
Konstantin Smolyanin

2
@Orion的简单答案是将数组视为对象。要获得更详细的答案,您将不得不继续阅读,typeof因为它有一些特殊情况并不一定具有很大的意义。如果您试图区分数组和非数组对象,那么您绝对不想使用typeof
马特·芬威克

8
@Tresdin最好的方法是运行Object.prototype.toString.call(yourVar),成为yourVar您需要检查的内容。如果是数组,则Object.prototype.toString.call([1,2])返回[object Array]
Jose Rui Santos

537

让我们在Javascript中定义“对象”。根据MDN docs,每个值都是对象或基元:

原始的原始值

不是对象且没有任何方法的数据。JavaScript具有5种原始数据类型:字符串,数字,布尔值,空值,未定义。

什么是原始语?

  • 3
  • 'abc'
  • true
  • null
  • undefined

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

  • Object.prototype
  • 一切都源于 Object.prototype
    • Function.prototype
      • Object
      • Function
      • function C(){} -用户定义的功能
    • C.prototype-用户定义函数的prototype属性:这不是 C s的原型
      • new C() -“新”-用户定义的功能
    • Math
    • Array.prototype
      • 数组
    • {"a": 1, "b": 2} -使用文字符号创建的对象
    • new Number(3) -围绕原语的包装
    • ... 许多其他事情 ...
  • Object.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,如果其参数不是对象,则抛出异常

// 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({})

22
obj === Object(obj)返回true数组。
OnurYıldırım2016年

5
var x = []; console.log(x === Object(x)); // return true
照明者

6
正如我在回答中提到的,@ Illuminator数组 Javascript 中的对象。
马特·芬威克

1
getPrototypeOf不适用于已吊销的代理,吊销是对象,但会抛出。
Oriol

2
为什么不({}).toString.apply(obj) === '[object Object]'这样区分数组和不是数组的对象
MauricioJuanes

295

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;
};

57
在javascript中,数组也是一个对象,因此大多数时候您都希望排除该数组:return obj === Object(obj) && Object.prototype.toString.call(obj) !== '[object Array]'
Daan

22
为什么要排除数组?它们是成熟的对象。
Nikolai 2014年

65
因为大多数时候您都想将{}与[]区别开来,例如在函数中输入
Daan

5
@Nickolai ..并用于遍历嵌套对象。
瑞奇·博伊斯

6
好答案。也可以处理null。应该是公认的答案。
蒂芬(Tiffon)2015年

179

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

  • "[object Object]" 如果myVar是对象
  • "[object Array]" 如果myVar是一个数组
  • 等等

有关此的更多信息以及为什么它是typeof的很好替代方法,请查看本文


12
我最近了解到typeof [] === 'object'-> true。那就是您需要的这种方法。
Jondlm

3
@Christophe不区分基元和对象Object.prototype.toString.call(3)-> "[object Number]"Object.prototype.toString.call(new Number(3))-> "[object Number]
Matt Fenwick 2014年

3
@MattFenwick我不认为这是OP试图识别的“对象”
Christophe

3
@Christophe为什么这么认为?恕我直言,在OP没有为“对象”给出任何其他定义的情况下,我认为在整个ECS规范中始终使用的定义是最合理的。
马特·芬威克

getType=function(obj){return Object.prototype.toString.call(obj).match(/\[object (\w+)\]/)[1];};
Polywhirl先生2014年

115

用于简单地检查对象或数组,而无需其他函数调用(速度)。就像也在这里张贴。

isArray()

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

isObject() -注意:仅用于对象文字,因为它对自定义对象(例如新的Date或新的YourCustomObject)返回false。

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

isObject仅适用于对象文字。如果我创建一个自定义类型,创建该类型的实例并对其进行测试,则它将返回false
WickyNilliams 2013年

3
@zupa:!! a是什么?

4
@ 3000好了,如果我们忽略(!! a)部分,它将崩溃,因为null和undefined没有构造函数。(!! a)过滤掉它们。这是否回答你的问题?
zupa 2015年

2
@zupa @ 3000 Boolean(a)更长,但更直观。只是不要使用new Boolean(a):(这就是原因)!
JayVee

10
惊讶的是,最佳答案远非如此。这基本上回答了这个问题-是否可以JSON形式将其表示为以{字符开头的内容。对于数组的情况,只要不需要支持IE <9,就可以Array.isArray()用来确定某物是否是数组。它通过了您提供的所有测试用例。
基普(Kip)

81

我很喜欢:

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

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

DOCS:

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


3
那么console.log(isObject(new Date()))呢?为什么日期应该是对象而不是数组?
schirrmacher

5
@macher因为new Date()返回一个对象。从逻辑的角度来看,数组不是对象,尽管JavaScript会这样处理并报告它们。然而,实际上,将它们视为相等是没有帮助的,因为它们并不相等。length例如,对象没有属性,也没有类似push()的方法。有时您可能想给函数提供重载参数,在这种情况下,您需要在数组或对象之间进行区别,特别是如果其他参数取决于给定的参数。
StanE '16

1
@StanE数组绝对是对象。不确定为什么您认为对象不能具有length属性或方法(例如pushObject.create(Array.prototype)是包含这些对象的非数组对象的简单反例。使数组与众不同的是它们是带有自定义[[DefineOwnProperty]]基本内部方法的奇异对象,但它们仍然是对象。
Oriol

4
@Oriol我既没有写数组不是对象,也没有写对象不能具有length属性(我的意思是对象文字length默认情况下没有属性)。从逻辑角度看,我写道数组不是对象。我说的是程序逻辑。有时有必要检查数组是否为“真实”数组,并且绝对不是“真实”对象。那Array.isArray()是为了什么 假设您有一个接受一个对象或对象数组的函数。检查特殊属性或方法是一种肮脏的解决方案。本机方法总是更好。
StanE

2
typeof null"object",不是"undefined"
2540625

80

具有功能Array.isArray

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

没有功能 Array.isArray

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

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';
}

它不能在前面提到的所有测试用例中正常工作,但是对于所有对象(纯对象或构造对象)都足够好。


isObject如果Object.create(null)由于内部实现在这里Object.create说明而无法使用,但是您可以在更复杂的实现中使用: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;
};

基于此实现,已经在npm v1上创建了软件包!它适用于所有先前描述的测试用例!🙂


最佳答案!适用于此处
prieston

因为这为isObject(myDateObject)返回false,所以这不是问题的答案。仅当变量是特定类的对象时,它才告诉变量是否为对象。这里的问题是针对对任何对象返回true的通用函数。
Yetanotherjosh

@Yetanotherjosh确实是一个答案🤓您提到了答案中描述的情况,并且要点-您必须使用isDateyourDateObject来编写健壮的代码,否则您将拥有脆弱的isObject方法。
V. Kovpak '18

@VladimirKovpak Date在我的评论中使用错误,因为是的,答案的确讨论了Date。但这Date只是无限可能的类之一,这一点对于其他任何类都成立。示例:class Foo() { }; var x = new Foo(); isObject(x)return false。我不确切知道OP的用例是什么,但是很容易想到这样的场景:在这些场景中,必须了解所有可能的类专门针对每个进行检查。
Yetanotherjosh

@Yetanotherjosh我已经更新了答案。并增加了1个案例。
V. Kovpak

40

哦,我的上帝!我认为这可能比以往更短,让我们看看:

简短代码和最终代码

function isObject(obj)
{
    return obj != null && obj.constructor.name === "Object"
}

console.log(isObject({})) // returns true
console.log(isObject([])) // returns false
console.log(isObject(null)) // returns false

讲解

返回类型

类型的JavaScript对象(包括null)返回"object"

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

检查他们的构造函数

检查其constructor属性将返回具有其名称的函数。

console.log(({}).constructor) // returns a function with name "Object"
console.log(([]).constructor) // returns a function with name "Array"
console.log((null).constructor) //throws an error because null does not actually have a property

引入Function.name

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

console.log(({}).constructor.name) // returns "Object"
console.log(([]).constructor.name) // returns "Array"
console.log((null).constructor.name) //throws an error because null does not actually have a property

注意:从2018年开始,Function.name可能无法在IE https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Function/name#Browser_compatibility中运行


3
我真的很喜欢这个,简而言之。据我所知,它仅在1件事上失败。如果obj = Object.create(null)以及为什么仍然要这么做...?
朱利安·奈特

29

好的,让我们在回答问题之前先给您一个概念,在JavaScript函数中,对象是Object,null,Object,Arrays甚至Date。因此,您看到没有像typeof obj ==='object'这样的简单方法,所以上述所有内容都将返回true,但是有一些方法可以通过编写函数或使用JavaScript框架进行检查,确定:

现在,假设您有一个真实的对象(不是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中完成的,我在函数前面的注释中提到了这一点,他们将Array视为对象...在此处查看更多信息:docs .angularjs.org / api / ng / function / angular.isObject
Alireza

24

这取决于您对“是对象”的意思。如果您希望所有不是原始类型的东西(即可以设置新属性的东西),都可以做到这一点:

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

它不包括原语(纯数字/ NaN/ Infinity,普通字符串,符号,true/ falseundefinednull),但应返回其他一切(包括真正的NumberBooleanString对象)。请注意,JS没有定义与一起使用时应返回的“宿主”对象(例如window或),因此很难用这样的检查来覆盖这些对象。consoletypeof

如果您想知道某事物是否是“普通”对象,即它是作为文字创建的{}还是使用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;
    }
}

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


为什么typeof ==='function'被视为对象?函数不是对象,不是吗?“ new myFunc()”将成为一个对象,是的,但是一个普通的函数?
StanE '16

不,每个函数都是Javascript中的对象,无论其创建方式如何。你可以对它们设置属性(除非它们被冻结),他们是instanceof Object,两个相同的功能文字是不严格相等,它们通过引用等传递
最后的孩子

21

天哪,其他答案太混乱了。

简短答案

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

要测试这一点,只需在chrome控制台中运行以下语句。

情况1。

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

情况二

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中检查数组。


2
值得注意的是,falseanyVar是一个函数时,它也会返回(根据需要)。
杰米·伯奇

18

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

  • 它返回"object"null,属于空类型。
  • 它返回 "function"属于对象类型的可调用对象。
  • 它可以返回(几乎)非标准的不可调用对象所需的任何内容。例如,IE似乎喜欢"unknown"。唯一禁止的结果是"function"和原始类型。

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

因此,代替typeof,我只推荐其结果根据值是否为对象而变化的方法。以下打算成为

全面但不详尽的列表,列出了测试值是否属于对象类型的正确方法。

  • Object 建设者

    Object构造胁迫传递的参数的对象。如果已经是一个对象,则返回相同的对象。

    因此,您可以使用它来将值强制转换为对象,并将该对象与原始值进行严格比较。

    以下功能需要ECMAScript 3,它引入了===

    function isObject(value) { /* Requires ECMAScript 3 or later */
      return Object(value) === value;
    }

    我喜欢这种方法,因为它简单且可自我描述,并且类似的检查也适用于布尔值,数字和字符串。但是,请注意,它依赖于全局Object不被遮盖或更改。

  • 建设者

    实例化构造函数时,它可以返回与刚创建的实例不同的值。但是该值将被忽略,除非它是一个对象。

    以下函数需要ECMAScript 3,它允许构造函数返回非对象。在ECMAScript 3之前抛出了一个错误,但是try那时不存在语句。

    function isObject(value) { /* Requires ECMAScript 3 or later */
      return new function() { return value; }() === value;
    }

    虽然比上一个示例简单一些,但是此示例不依赖任何全局属性,因此可能是最安全的。

  • this

    旧的ECMAScript规范要求该this值是一个对象。引入了ECMAScript 3 Function.prototype.call,该方法允许调用具有任意this值的函数,但可以将其强制为一个对象。

    ECMAScript 5引入了一种严格的模式,该模式消除了此行为,但是在草率模式下,我们仍然可以(但可以说不应)依靠它。

    function isObject(value) { /* Requires ECMAScript 3 or later in sloppy mode */
      return function() { return this === value; }.call(value);
    }
  • [[原型]]

    所有普通对象都有一个名为[[Prototype]]的内部插槽,该插槽的值确定了它从哪个其他对象继承。该值只能是一个对象或null。因此,您可以尝试创建一个从所需值继承的对象,并检查其是否起作用。

    无论Object.createObject.getPrototypeOf需要的ECMAScript 5。

    function isObject(value) { /* Requires ECMAScript 5 or later */
      try {
        Object.create(value);
        return value !== null;
      } catch(err) {
        return false;
      }
    }
    function isObject(value) { /* Requires ECMAScript 5 or later */
      function Constructor() {}
      Constructor.prototype = value;
      return Object.getPrototypeOf(new Constructor()) === value;
    }
  • 一些新的ECMAScript 6种方式

    ECMAScript 6引入了一些新的间接方法来检查值是否是对象。他们使用以前看到的方法将值传递给一些需要对象的代码,该对象包装在try语句中以捕获错误。一些隐藏的例子,不值得评论


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


2
“只有我的回答和大安的回答是完全正确的。” 鉴于我完全不同意您的前两个句子,这有点冒昧。
zzzzBov

1
@zzzzBov好吧,我查看了所有答案,除了我和大安的答案,他们不能保证总是返回正确的答案。我可以为大多数示例提供可重复的反例。其他人建议检查typeof是否返回“功能”或“对象”,但是正如我所解释的,规范允许某些对象获得其他结果。马特·芬威克(Matt Fenwick)的答案与达安(Daan)的答案相同,但也有不正确的答案。
Oriol

1
我不同意您的答案是“完全正确”的前提,我认为其他人“不能确保总是返回正确的答案”不会以任何方式驳斥我的立场。此外,该问题并未就什么输入应该产生什么输出提出任何要求。
zzzzBov

1
@zzzzBov该问题询问如何检查某物是否为对象。ECMAScript定义对象是什么,因此我使用该定义。我看不到任何其他合理的解释。做其他事情的答案(例如排除数组)在某些情况下可能很有用,但它们不会检查某些东西是否是对象。
Oriol


15

尝试这个

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

14
为什么您要检查布尔值?
jkutianski 2013年

5
这错过了两种情况:Object.prototype instanceof Object->错误。 Object.create(null) instanceof Object->错误。
马特·芬威克

日期呢?new Date() instanceof Object => true
mauron85

13

准备使用的功能进行检查

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中,nullObjectArrayDatefunctions为所有对象。虽然,null有点人为。因此,最好检查第null一个,以检测它是否不为空。

  • 检查typeof o === 'object'保证o是一个对象。没有此检查,Object.prototype.toString将毫无意义,因为它将返回对象,即使对于undefinedand null!例如:toString(undefined)return [object Undefined]

    typeof o === 'object'检查,toString.call(O)是检查是否一个伟大的方法o是一个对象,一个派生对象像ArrayDate或一个function

  • isDerivedObject函数中,它检查o是函数。因为,功能也是一个对象,所以才存在它。如果不这样做,函数将返回false。示例: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));
}

// TESTS

// is null an object?

console.log(
  'is null an object?', isObject(null)
);

console.log(
  'is null a derived object?', isDerivedObject(null)
);

// is 1234 an object?

console.log(
  'is 1234 an object?', isObject(1234)
);

console.log(
  'is 1234 a derived object?', isDerivedObject(1234)
);

// is new Number(1234) an object?

console.log(
  'is new Number(1234) an object?', isObject(new Number(1234))
);

console.log(
  'is new Number(1234) a derived object?', isDerivedObject(1234)
);

// is function object an object?

console.log(
  'is (new (function (){})) an object?', 
  isObject((new (function (){})))
);

console.log(
  'is (new (function (){})) a derived object?', 
  isObject((new (function (){})))
);

// is {} an object?

console.log(
  'is {} an object?', isObject({})
);

console.log(
  'is {} a derived object?', isDerivedObject({})
);

// is Array an object?

console.log(
  'is Array an object?',
  isObject([])
)

console.log(
  'is Array a derived object?',
  isDerivedObject([])
)

// is Date an object?

console.log(
  'is Date an object?', isObject(new Date())
);

console.log(
  'is Date a derived object?', isDerivedObject(new Date())
);

// is function an object?

console.log(
  'is function an object?', isObject(function(){})
);

console.log(
  'is function a derived object?', isDerivedObject(function(){})
);


13

如果您想检查prototypefor的object唯一来源Object。过滤掉StringNumberArrayArguments,等。

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

或作为单表达式箭头功能(ES6 +)

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

1
这是最好的方法,但在第二行,我将使其变得更加容易:return Object.prototype.toString.call(n) === '[object Object]'
mesqueeb

1
您也可以删除null支票,因为Object.prototype.toString.call(null) === '[object Null]'
Gust van de

12
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也都有一个type object。要仅获取真实对象,需要使用instanceof运算符检查继承链。它将消除null,但是Array在继承链中具有Object。

因此解决方案是:

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

/./ instanceof Object //true
yckart

11

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

function isPlainObject(o) {
   return ((o === null) || Array.isArray(o) || typeof o == 'function') ?
           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对象,您的方法将失败。
Grzegorz Pawlik

9

lodash具有isPlainObject,这可能是许多访问此页面的人正在寻找的东西。给定函数或数组时返回false。


完善!我知道_.isObjectJS将哪个对象视为对象。但是我通常需要的是区分对象文字和数组,这正是_.isPlainObject我所要做的。
青柠

9

这将起作用。它是一个返回true,false或可能为null的函数。

const isObject = obj => obj && obj.constructor && obj.constructor === Object;

console.log(isObject({})); // true
console.log(isObject([])); // false
console.log(isObject(new Function)); // false
console.log(isObject(new Number(123))); // false
console.log(isObject(null)); // null


2
@SeregPie将来,您应该避免编辑答案中的代码。按照这个答案,在测试时,我确实获得null了最终测试的结果,而不是false。请参阅何时应该对代码进行编辑?
尼克,

9

由于对如何正确处理此问题似乎有很多困惑,我将留下2美分(此答案符合规范,并在所有情况下都能产生正确的结果):

测试原语: undefined null boolean string number

function isPrimitive(o){return typeof o!=='object'||null}

对象不是原始的:

function isObject(o){return !isPrimitive(o)}

或者:

function isObject(o){return o instanceof Object}
function isPrimitive(o){return !isObject(o)}

测试任何阵列:

const isArray=(function(){
    const arrayTypes=Object.create(null);
    arrayTypes['Array']=true;
    arrayTypes['Int8Array']=true;
    arrayTypes['Uint8Array']=true;
    arrayTypes['Uint8ClampedArray']=true;
    arrayTypes['Int16Array']=true;
    arrayTypes['Uint16Array']=true;
    arrayTypes['Int32Array']=true;
    arrayTypes['Uint32Array']=true;
    arrayTypes['BigInt64Array']=true;
    arrayTypes['BigUint64Array']=true;
    arrayTypes['Float32Array']=true;
    arrayTypes['Float64Array']=true;
    return function(o){
        if (!o) return false;
        return !isPrimitive(o)&&!!arrayTypes[o.constructor.name];
    }
}());

测试对象,不包括:Date RegExp Boolean Number String Function任何数组

const isObjectStrict=(function(){
    const nativeTypes=Object.create(null);
    nativeTypes['Date']=true;
    nativeTypes['RegExp']=true;
    nativeTypes['Boolean']=true;
    nativeTypes['Number']=true;
    nativeTypes['String']=true;
    nativeTypes['Function']=true;
    return function(o){
        if (!o) return false;
        return !isPrimitive(o)&&!isArray(o)&&!nativeTypes[o.constructor.name];
    }
}());

8

当其他所有方法都失败时,我将使用以下方法:

var isObject = function(item) {
   return item.constructor.name === "Object";
}; 

1
为什么比较字符串,为什么不简单item.constructor === Object
K3 --- rnc

null引发异常Uncaught TypeError: Cannot read property 'constructor' of null(…)
Vitim.us

@rounce我的目标是支持较旧的IE版本,为什么它在IE中不起作用?是因为indexOf还是因为constructor.name
Jankapunkt

8

Ramda功能库具有用于检测JavaScript类型中一个精彩功能。

解释完整功能

function type(val) {
  return val === null      ? 'Null'      :
         val === undefined ? 'Undefined' :
         Object.prototype.toString.call(val).slice(8, -1);
}

当我意识到解决方案多么简单和美观时,我不得不大笑。

Ramda 文档中的用法示例:

R.type({}); //=> "Object"
R.type(1); //=> "Number"
R.type(false); //=> "Boolean"
R.type('s'); //=> "String"
R.type(null); //=> "Null"
R.type([]); //=> "Array"
R.type(/[A-z]/); //=> "RegExp"
R.type(() => {}); //=> "Function"
R.type(undefined); //=> "Undefined"

8

阅读和尝试了很多的实现之后,我发现很少有人尝试检查类似值JSONMathdocument再与原型链或物体比1步。

typeof我认为最好是将检查保持尽可能简单,以免在添加新的原始对象或本机对象注册为typeof“对象” 时进行重构,而不是检查变量的大小写然后消除边缘情况。'。

毕竟,typeof操作员会告诉您某个对象是否是JavaScript的对象,但是JavaScript的对象定义对于大多数实际场景(例如typeof null === 'object')而言太宽泛了。下面是一个函数,该函数v通过本质上重复两次检查来确定变量是否为对象:

  1. 一个循环开始,只要区域的字符串版本继续v'[object Object]'
    我希望函数的结果与下面的日志完全一样,所以这是我最后得到的唯一“对象”条件。如果失败,该函数立即返回false。
  2. v被替换为链中的下一个原型v = Object.getPrototypeOf(v),但之后也直接进行评估。当新值v是时null,表示每个原型,包括根原型(很可能是链中唯一的原型)都已通过while循环中的检查,我们可以返回true。否则,将开始新的迭代。

function isObj (v) {
  while (     Object.prototype.toString.call(v) === '[object Object]')
  if    ((v = Object.getPrototypeOf(v))         === null)
  return true
  return false
}

console.log('FALSE:')
console.log('[]                   -> ', isObj([]))
console.log('null                 -> ', isObj(null))
console.log('document             -> ', isObj(document))
console.log('JSON                 -> ', isObj(JSON))
console.log('function             -> ', isObj(function () {}))
console.log('new Date()           -> ', isObj(new Date()))
console.log('RegExp               -> ', isObj(/./))

console.log('TRUE:')
console.log('{}                   -> ', isObj({}))
console.log('new Object()         -> ', isObj(new Object()))
console.log('new Object(null)     -> ', isObj(new Object(null)))
console.log('new Object({})       -> ', isObj(new Object({foo: 'bar'})))
console.log('Object.prototype     -> ', isObj(Object.prototype))
console.log('Object.create(null)  -> ', isObj(Object.create(null)))
console.log('Object.create({})    -> ', isObj(Object.create({foo: 'bar'})))
console.log('deep inheritance     -> ', isObj(Object.create(Object.create({foo: 'bar'}))))


6
if(typeof value === 'object' && value.constructor === Object)
{
    console.log("This is an object");
}

1
如果value是的话,null这将引发错误……
Gershom

当然,这将是false针对对象的Object.assign({}, {constructor: null})
user4642212

6

如果明确想检查给定的值是否为{}

function isObject (value) {
 return value && typeof value === 'object' && value.constructor === Object;
}

6
const isObject = function(obj) {
  const type = typeof obj;
  return type === 'function' || type === 'object' && !!obj;
};

!!obj是检查是否obj真实的简写(以筛选出null


6

这是一个古老的问题,但被认为应该留在这里。大多数人都在检查变量是否{}意味着键值配对,而不是JavaScript用于给定事物的下划线构造,老实说,JavaScript中的大多数东西都是对象。因此,将其删除。如果你做...

let x = function() {}
typeof x === 'function' //true
x === Object(x) // true
x = []
x === Object(x) // true

// also
x = null
typeof null // 'object'

大多数时候,我们想要知道的是我们是否有API的资源对象或ORM返回的数据库调用。然后,我们可以测试是否不是Array,不是null,不是typeof 'function'以及是Object

// To account also for new Date() as @toddmo pointed out

x instanceof Object && x.constructor === Object

x = 'test' // false
x = 3 // false
x = 45.6 // false
x = undefiend // false
x = 'undefiend' // false
x = null // false
x = function(){} // false
x = [1, 2] // false
x = new Date() // false
x = {} // true

持久性有机污染物truenew Date()
toddmo

1
@toddmo感谢您指出这一点。现在示例代码为new Date()
Gilbert

4

我喜欢用的是这个

function isObject (obj) {
  return typeof(obj) == "object" 
        && !Array.isArray(obj) 
        && obj != null 
        && obj != ""
        && !(obj instanceof String)  }

我认为在大多数情况下,日期必须作为对象通过检查,因此我不过滤日期


4

我从这个SO问题中找到了一种执行这种类型检查的“新”方法: 为什么instanceof对某些文字返回false?

从此,我创建了一个用于类型检查的函数,如下所示:

function isVarTypeOf(_var, _type){
    try {
        return _var.constructor === _type;
    } catch(ex) {
        return false;         //fallback for null or undefined
    }
}

那么您可以这样做:

console.log(isVarTypeOf('asdf', String));   // returns true
console.log(isVarTypeOf(new String('asdf'), String));   // returns true
console.log(isVarTypeOf(123, String));   // returns false
console.log(isVarTypeOf(123, Number));   // returns true
console.log(isVarTypeOf(new Date(), String));   // returns false
console.log(isVarTypeOf(new Date(), Number));   // returns false
console.log(isVarTypeOf(new Date(), Date));   // returns true
console.log(isVarTypeOf([], Object));   // returns false
console.log(isVarTypeOf([], Array));   // returns true
console.log(isVarTypeOf({}, Object));   // returns true
console.log(isVarTypeOf({}, Array));   // returns false
console.log(isVarTypeOf(null, Object));   // returns false
console.log(isVarTypeOf(undefined, Object));   // returns false
console.log(isVarTypeOf(false, Boolean));   // returns true

已在Chrome 56,Firefox 52,Microsoft Edge 38,Internet Explorer 11,Opera 43上测试过

编辑:
如果您还想检查变量是否为null或未定义,则可以改用以下方法:

function isVarTypeOf(_var, _type){
    try {
        return _var.constructor === _type;
    } catch(ex) {
        return _var == _type;   //null and undefined are considered the same
        // or you can use === if you want to differentiate them
    }
}

var a = undefined, b = null;
console.log(isVarTypeOf(a, undefined)) // returns true
console.log(isVarTypeOf(b, undefined)) // returns true
console.log(isVarTypeOf(a, null)) // returns true

从inanc的评论更新:接受挑战:D

如果要松散比较对象,可以尝试这种方式:

function isVarTypeOf(_var, _type, looseCompare){
    if (!looseCompare){
        try {
            return _var.constructor === _type;
        } catch(ex){
            return _var == _type;
        }
    } else {
        try{
            switch(_var.constructor){
                case Number:
                case Function:
                case Boolean:
                case Symbol:
                case Date:
                case String:
                case RegExp:
                    // add all standard objects you want to differentiate here
                    return _var.constructor === _type;
                case Error:
                case EvalError:
                case RangeError:
                case ReferenceError:
                case SyntaxError:
                case TypeError:
                case URIError:
                    // all errors are considered the same when compared to generic Error
                    return (_type === Error ? Error : _var.constructor) === _type;
                case Array:
                case Int8Array:
                case Uint8Array:
                case Uint8ClampedArray:
                case Int16Array:
                case Uint16Array:
                case Int32Array:
                case Uint32Array:
                case Float32Array:
                case Float64Array:
                    // all types of array are considered the same when compared to generic Array
                    return (_type === Array ? Array : _var.constructor) === _type;
                case Object:
                default:
                    // the remaining are considered as custom class/object, so treat it as object when compared to generic Object
                    return (_type === Object ? Object : _var.constructor) === _type;
            }
        } catch(ex){
            return _var == _type;   //null and undefined are considered the same
            // or you can use === if you want to differentiate them
        }
    }
}

这样,您可以像inanc的注释一样进行操作:

isVarTypeOf(new (function Foo(){}), Object); // returns false
isVarTypeOf(new (function Foo(){}), Object, true); // returns true

要么

Foo = function(){};
Bar = function(){};
isVarTypeOf(new Foo(), Object);   // returns false
isVarTypeOf(new Foo(), Object, true);   // returns true
isVarTypeOf(new Bar(), Foo, true);   // returns false
isVarTypeOf(new Bar(), Bar, true);   // returns true
isVarTypeOf(new Bar(), Bar);    // returns true

这无法检测到新类是否是对象。isVarTypeOf(new(function Foo(){}),Object)//返回false而不是true。请参阅下面的我的答案以进行正确的检查。
伊南克·古姆斯

但是,您可以instanceof用来检查对象。不过,这并不是一门精确的科学。
伊南克·古姆斯

@inanc,以及那是因为new Foo()回报Foo对象,相同的new String()回报String对象,或new Date()返回一个Date对象,你可以做Foo = function(){}; isVarTypeOf(new Foo(), Foo);
am05mhz

是的,那是我实际上所说的:您现在不在检查它是否是对象。
伊南克·古姆斯

@inanc干杯,我一直在寻找一种进行类型检查的方法(而不仅仅是对象),转到此页面和另一页,然后我太激动了,以至于我忘记了这个问题的内容,我的坏:)
am05mhz
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.