检查一个值是否是JavaScript中的对象

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

1954708 次浏览

更新

这个答案是不完整的,给出了误导性的结果。例如,null在JavaScript中也被认为是类型object,更不用说其他几个边缘情况了。按照下面的建议继续讨论其他"最赞成的(正确的!)答案"

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

原答复

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

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

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

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

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

试试这个

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

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

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

有关这方面的更多信息以及为什么它是typeof的良好替代品,看看这篇文章

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

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

更新

由于之前在V8中的bug和轻微的微速度优化,自underscore.js(2014年8月)以来,该方法如下所示:

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

用于简单地检查Object或Array而无需额外的函数调用(速度)。也发布了这里

isArray()

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

//文字对象-注意:仅用于对象文字,因为它为自定义对象返回false,例如new Date或new YourCustomObject。

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

我有一个有效的代码片段。当没有给出整段代码时,我觉得很困惑,所以我自己创建了它:

    <!DOCTYPE html><html><body><button onclick="myFunc()">Try it</button>
<script>var abc = new Number();// var abc = 4;//this is a code variation which will give a diff alert
function myFunc(){if(abc && typeof abc === "object")alert('abc is an object and does not return null value');elsealert('abc is not an object');}</script>
</body></html>

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

原始值

不是对象且没有任何方法的数据。JavaScript有7种原始数据类型:字符串、数字、bigint、布尔、未定义、符号和null。

什么是原始人?

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

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

  • Object.prototype
  • 一切都来自Object.prototype
    • Function.prototype
      • Object
      • Function
      • function C(){}--用户定义的函数
    • C.prototype--用户定义函数的原型属性:这是没有Cs原型
      • new C()--"new"-ing用户定义的函数
    • 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)) -> falsefunction isObject(val) {return val instanceof Object;}

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

// oops: isObject(Object) -> falsefunction 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') );}

@达恩的回答似乎也奏效了:

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

因为,根据MDN文档

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


第三种似乎有效的方法(不确定是否为100%)是使用Object.getPrototypeOf,如果其参数不是对象,则使用抛出异常

// these 5 examples throw exceptionsObject.getPrototypeOf(null)Object.getPrototypeOf(undefined)Object.getPrototypeOf(3)Object.getPrototypeOf('abc')Object.getPrototypeOf(true)
// these 5 examples don't throw exceptionsObject.getPrototypeOf(Object)Object.getPrototypeOf(Object.prototype)Object.getPrototypeOf(Object.create(null))Object.getPrototypeOf([])Object.getPrototypeOf({})

我喜欢简单地说:

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

如果项目是JS对象,它不是JS数组,也不是null……如果这三个条件都证明为真,则返回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

当其他一切都失败时,我使用这个:

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

Lodash有isPlainObject,这可能是许多访问此页面的人正在寻找的。当给出函数或数组时,它返回false。

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

!!obj是检查obj是否真实的简写(过滤掉null

如果你已经在使用AngularJS,那么它有一个内置的方法来检查它是否是一个对象(不接受null)。

angular.isObject(...)

对于“普通对象”(我的意思是,像{'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, falseconsole.debug(isPlainObject({'x': 6, 'y': 16})); //literal object, trueconsole.debug(isPlainObject(5)); //number, falseconsole.debug(isPlainObject(undefined)); //undefined, falseconsole.debug(isPlainObject(null)); //null, falseconsole.debug(isPlainObject('a')); //string, falseconsole.debug(isPlainObject([])); //array?, falseconsole.debug(isPlainObject(true)); //bool, falseconsole.debug(isPlainObject(false)); //bool, false

它总是为我工作。只有当“o”的类型是“对象”,但没有null、数组或函数时,if才会返回“true”。:)

这取决于你对“是一个对象”的意思。如果你想要所有不是原始的东西,即你可以设置新属性的东西,这应该可以做到:

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

它排除了原语(普通数字/NaN/Infinity、普通字符串、符号、true/falseundefinednull),但对于其他所有对象(包括NumberBooleanString对象)都应该返回true。请注意,JS没有定义与Infinity1一起使用时应该返回什么“主机”对象,例如windowInfinity0,因此很难用这样的检查来掩盖这些。

如果你想知道某个东西是“普通”对象,即它是作为文字{}还是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:因为#0现在允许自定义Object.prototype.toString.call(...)的输出,所以上面的isPlainObject函数在某些情况下可能会返回false,即使对象开始以文字形式存在。可以说,按照惯例,带有自定义字符串标签的对象不再完全是普通对象,但这进一步混淆了Javascript中普通对象的定义。

var isArray=function(value){if(Array.isArray){return Array.isArray(value);}else{return Object.prototype.toString.call(value)==='[object Array]';}}var isObject=function(value){return value !== null&&!isArray(value) && typeof value === 'object';}
var _val=new Date;console.log(isObject(_val));//trueconsole.log(Object.prototype.toString.call(_val)==='[object Object]');//false
var a = [1]typeof a //"object"a instanceof Object //truea instanceof Array //true
var b ={a: 1}b instanceof Object //trueb instanceof Array //false
var c = nullc instanceof Object //falsec instanceof Array //false

我被要求提供更多细节。检查我们的变量是否是对象的最干净和可理解的方法是typeof myVar。它返回一个具有类型(例如"object""undefined")的字符串。

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

所以解决方法是:

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

您可以使用Object.prototypetoString()方法轻松完成此操作

if(Object.prototype.toString.call(variable) == "[object Object]"){doSomething();}

if(Object.prototype.toString.call(variable).slice(8,-1).toLowerCase() == "object"){doSomething();}

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

  • 对于属于Null类型的null,它返回"object"
  • 对于属于Object类型的可调用对象,它返回"function"
  • 对于非标准的不可调用对象,它几乎可以返回任何它想要的东西。例如,IE似乎喜欢"unknown"。唯一禁止的结果是"function"和原始类型。

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

因此,与typeof不同,我只推荐其结果因值是否为对象而异的方法

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

  • #0构造函数

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

    虽然比前面的例子不那么简单,但这个例子不依赖任何全局属性,因此可能是最安全的。

  • #0值

    旧的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]]

    All ordinary objects have an internal slot called [[Prototype]], whose value determines from which other object it inherits from. The value can only be an object or null. Therefore, you can attempt to create an object which inherits from the desired value, and check if it worked.

    Both Object.create and Object.getPrototypeOf require 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;}
  • Some new ECMAScript 6 ways

    ECMAScript 6 introduces some new indirect ways to check is a value is an object. They use the previously seen approach to pass the value to some code which requires an object, wrapped inside a try statement to catch errors. Some hidden examples, not worth commenting

    function isObject(value) { /* Requires ECMAScript 6 or later */try {Object.setPrototypeOf({}, value);return value !== null;} catch(err) {return false;}}

    function isObject(value) { /* Requires ECMAScript 6 or later */try {new WeakSet([value]);return true;} catch(err) {return false;}}


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

直接回答当然是0,但这是非常没有用的。我想知道OP是否意味着一个普通的字典。

尝试:

isdict(v) { return  v !== undefined && v!==null && typeof v==='object' && v.constructor!==Array && v.constructor!==Date; }

一个小小的NodeJS控制台实验,基于对Matt Fenwick上面完整答案的第三个选项的阅读。只需稍微调整即可获得truefalse

以下对象测试返回false。

> if(Object.getPrototypeOf('v') === Object.prototype){console.log(true);}else{console.log(false);}falseundefined> if(Object.getPrototypeOf(1) === Object.prototype){console.log(true);}else{console.log(false);}falseundefined> if(Object.getPrototypeOf(false) === Object.prototype){console.log(true);}else{console.log(false);}falseundefined> if(Object.getPrototypeOf(['apple']) === Object.prototype){console.log(true);}else{console.log(false);}falseundefined

对象将返回true。

> if(Object.getPrototypeOf({'this':10}) === Object.prototype){console.log(true);}else{console.log(false);}trueundefined

准备使用检查功能

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将毫无意义,因为它将为所有事物返回对象,即使是undefinednull!例如:toString(undefined)返回[object Undefined]

    typeof o === 'object'检查之后,toString.call(o)是检查o是否是对象、ArrayDatefunction等派生对象的好方法。

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

好的,在回答你的问题之前,让我们先给你这个概念,在JavaScript中,函数是对象,也有null,对象,数组甚至日期,所以你看到有没有一个简单的方法,比如typeof obj==='对象',所以上面提到的一切都将返回true,但是有一些方法可以通过编写函数或使用JavaScript框架来检查它,OK:

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

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

纯JavaScript:

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

//make sure the second object is capitalisedfunction 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);

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

const isObject = obj => obj && obj.constructor && obj.constructor === Object;
console.log(isObject({})); // trueconsole.log(isObject([])); // falseconsole.log(isObject(new Function)); // falseconsole.log(isObject(new Number(123))); // falseconsole.log(isObject(null)); // null

我从这个SO问题中找到了一种“新”方法来进行这种类型检查:为什么instance of对于某些文字返回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 trueconsole.log(isVarTypeOf(new String('asdf'), String));   // returns trueconsole.log(isVarTypeOf(123, String));   // returns falseconsole.log(isVarTypeOf(123, Number));   // returns trueconsole.log(isVarTypeOf(new Date(), String));   // returns falseconsole.log(isVarTypeOf(new Date(), Number));   // returns falseconsole.log(isVarTypeOf(new Date(), Date));   // returns trueconsole.log(isVarTypeOf([], Object));   // returns falseconsole.log(isVarTypeOf([], Array));   // returns trueconsole.log(isVarTypeOf({}, Object));   // returns trueconsole.log(isVarTypeOf({}, Array));   // returns falseconsole.log(isVarTypeOf(null, Object));   // returns falseconsole.log(isVarTypeOf(undefined, Object));   // returns falseconsole.log(isVarTypeOf(false, Boolean));   // returns true

这在Chrome56,Firefox 52,Microsoft Edge38,Internet Explorer 11,Opera 43上进行了测试

编辑:
如果您还想检查变量是否为空或未定义,您可以改为使用:

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 trueconsole.log(isVarTypeOf(b, undefined)) // returns trueconsole.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 herereturn _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 Errorreturn (_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 Arrayreturn (_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 Objectreturn (_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 falseisVarTypeOf(new (function Foo(){}), Object, true); // returns true

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

我喜欢用的是这个

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

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

使用typeof(my_obj)将告诉它是哪种类型的变量。

对于数组:Array.isArray(inp)[] isinstanceof Array

如果是对象将显示“对象”

简单的JS函数,

function isObj(v) {return typeof(v) == "object"}

例如:

function isObj(v) {return typeof(v) == "object"}
var samp_obj = {"a" : 1,"b" : 2,"c" : 3}
var num = 10;var txt = "Hello World!"var_collection = [samp_obj, num, txt]for (var i in var_collection) {if(isObj(var_collection[i])) {console.log("yes it is object")}else {console.log("No it is "+ typeof(var_collection[i]))}}

使用函数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: trueconsole.log(isObject([]));             // Will return: falseconsole.log(isObject(null));           // Will return: falseconsole.log(isObject(/.*/));           // Will return: falseconsole.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: falseconsole.log(isDate(d));   // Will return: true

因此,您将拥有严格而健壮的代码!


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

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

它不会对前面提到的所有测试用例正常工作,但它对所有对象(普通或构造)都足够好。


isObjectObject.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!它适用于前面描述的所有测试用例!🙂

它取决于用例,如果我们不想让数组和函数成为对象,我们可以使用underscore.js内置函数。

    function xyz (obj) {if (_.isObject(obj) && !_.isFunction(obj) && !_.isArray(obj)) {// now its sure that obj is an object}}
if(typeof value === 'object' && value.constructor === Object){console.log("This is an object");}

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"

如果您想检查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]'

大多数情况下使用typeof obj[index] === 'object',但它也会返回function#document,它们是一个对象。是否需要将其包含在结果中取决于您。

基本上,您可以通过检查控制台中的输出来执行测试代码,过滤掉特定元素是否是对象。在这里,您可以仅为示例运行代码:

function cekObject(obj, index) {if (!obj.tagName) {
//test case #1if (typeof obj === 'object') {console.log('obj['+ index +'] is listed as an object');}    
}}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.2.3/jquery.min.js"></script><script>function updateFilters() {var object = $('.j-image');$('.juicer-feed').empty();    
for(var index in object) {cekObject(object[index], index);};}</script>
<ul class="juicer-feed" data-feed-id="chetabahana" data-after="updateFilters()"></ul><script src="https://assets.juicer.io/embed.js"></script>

你可以使用JSON.stringify来测试你的Object,如下所示:

var test = {}if(JSON.stringify(test)[0] === '{') {console.log('this is a Object')}

考虑-typeof bar === "object"来确定bar是否是对象

尽管typeof bar === "object"是检查bar是否是对象的可靠方法,但JavaScript中令人惊讶的问题是null也被视为对象!

因此,令大多数开发人员惊讶的是,以下代码将向控制台记录true(而不是false):

var bar = null;console.log(typeof bar === "object"); // logs true!只要意识到这一点,就可以通过检查bar是否为null来轻松避免问题:

console.log((bar !== null) && (typeof bar === "object")); // logs false在我们的回答中,有两件事值得注意:

首先,如果bar是一个函数,上述解决方案将返回false。在大多数情况下,这是所需的行为,但在你也想为函数返回true的情况下,你可以将上述解决方案修改为:

console.log((bar !== null) && ((typeof bar === "object") || (typeof bar === "function")));其次,如果bar是一个数组(例如,如果var bar = [];),上述解决方案将返回true。在大多数情况下,这是所需的行为,因为数组确实是对象,但在您希望数组也为false的情况下,您可以将上述解决方案修改为:

console.log((bar !== null) && (typeof bar === "object") && (toString.call(bar) !== "[object Array]"));但是,还有另一种选择,对于空值、数组和函数返回false,但对于对象返回true:

console.log((bar !== null) && (bar.constructor === Object));或者,如果您使用jQuery:

console.log((bar !== null) && (typeof bar === "object") && (! $.isArray(bar)));

ES5使数组的情况非常简单,包括它自己的null检查:

console.log(Array.isArray(bar));

哦,我的上帝!我想这可能比以往任何时候都短,让我们看看这个:

简短和最终代码

function isObject(obj){return obj != null && obj.constructor.name === "Object"}
console.log(isObject({})) // returns trueconsole.log(isObject([])) // returns falseconsole.log(isObject(null)) // returns false

解释

返回类型

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

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

Checking on Their constructors

Checking on their constructor property returns function with their names.

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可能无法在IEhttps://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/name#Browser_compatibility工作

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

简短回答

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

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

原语测试:undefinednullbooleanstringnumber

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];}}());

对象测试不包括:DateRegExpBooleanNumberStringFunction任何数组

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];}}());

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

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

在阅读并尝试了很多实现之后,我注意到很少有人尝试检查JSONMathdocument等值或原型链长于1步的对象。

与其检查我们变量的typeof,然后破解边缘情况,我认为如果检查尽可能简单,以避免在添加新原语或本机对象时重构,注册为“对象”的typeof会更好。

毕竟,typeof运算符会告诉你是JavaScript的对象,但JavaScript对对象的定义对于大多数现实场景(例如typeof null === 'object')来说过于宽泛。下面是一个函数,它通过重复两次检查来确定变量v是否是对象:

  1. 只要v的字符串版本是'[object Object]',就会启动一个循环。
    我希望函数的结果与下面的日志完全相同,所以这是我最终得到的唯一“客观性”标准。如果失败,函数立即返回false。
  2. v被替换为链中带有v = Object.getPrototypeOf(v)的下一个原型,但之后也直接求值。当v的新值为null时,这意味着每个原型包括根原型(很可能是链中的只有原型)已经通过了if循环中的检查,我们可以返回true。否则,新的迭代开始。

function isObj (v) {while (     Object.prototype.toString.call(v) === '[object Object]')if    ((v = Object.getPrototypeOf(v))         === null)return truereturn 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'}))))

这是一个古老的问题,但被认为留在这里。大多数人都在检查变量是否为{},这意味着键值配对,而不是JavaScript用于给定事物的下划线结构,因为说实话,JavaScript中的大部分内容都是一个对象。所以把它拿出来。如果你这样做…

let x = function() {}typeof x === 'function' //truex === Object(x) // truex = []x === Object(x) // true
// alsox = nulltypeof null // 'object'

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

// To account also for new Date() as @toddmo pointed out
x instanceof Object && x.constructor === Object
x = 'test' // falsex = 3 // falsex = 45.6 // falsex = undefiend // falsex = 'undefiend' // falsex = null // falsex = function(){} // falsex = [1, 2] // falsex = new Date() // falsex = {} // true
function isObjectLike(value) {return value != null && typeof value == 'object' && !Array.isArray(value);}

基于豆沙

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

const isObj = o => o?.constructor === Object;
// True for thisconsole.log(isObj({}));        // object!
// False for theseconsole.log(isObj(0));         // numberconsole.log(isObj([]));        // arrayconsole.log(isObj('lol'));     // stringconsole.log(isObj(null));      // nullconsole.log(isObj(undefined)); // undefinedconsole.log(isObj(() => {}));  // functionconsole.log(isObj(Object));    // class

为了我的代码的目的,我发现了这个决定,它与上面的一些答案相对应:

ES6变体:

const checkType = o => Object.prototype.toString.call(o).replace(/\[|object\s|\]/g, '').toLowerCase();

ES5变体:

function checkType(o){return Object.prototype.toString.call(o).replace(/\[|object\s|\]/g, '').toLowerCase();}

你可以非常简单地使用它:

checkType([]) === 'array'; // truecheckType({}) === 'object'; // truecheckType(1) === 'number'; // truecheckType('') === 'string'; // truecheckType({}.p) === 'undefined'; // truecheckType(null) === 'null'; // true

等等…

性能

今天2020.09.26我在Chromev85、Safariv13.1.2和Firefox v80上对MacO HighSierra 10.13.6进行测试,以获取所选解决方案。

搜索结果

  • 解决方案C和H在所有浏览器上都是快速/最快的
  • 解决方案D和G在所有浏览器上都是最慢/最慢的

在此处输入图片描述

详情

我为解决方案执行3个测试用例ABCDEFGHIJKLMNOPQRSTUV

  • 对于小对象-你可以运行它这里
  • 对于大对象-你可以运行它这里
  • 没有对象-你可以运行它这里

下面的片段展示了解决方案之间的差异。解决方案A-G为马特·芬威克描述的选定案例给出了正确的答案

// https://stackoverflow.com/a/14706877/860099function A(x) {return x === Object(x);};
// https://stackoverflow.com/a/42250981/860099function B(x) {return _.isObject(x);}
// https://stackoverflow.com/a/34864175/860099function C(x) {return x != null && (typeof x === 'object' || typeof x === 'function');}
// https://stackoverflow.com/a/39187058/860099function D(x) {return new function() { return x; }() === x;}
// https://stackoverflow.com/a/39187058/860099function E(x) {return function() { return this === x; }.call(x);}
// https://stackoverflow.com/a/39187058/860099function F(x) { /* Requires ECMAScript 5 or later */try {Object.create(x);return x !== null;} catch(err) {return false;}}
// https://stackoverflow.com/a/39187058/860099function G(x) { /* Requires ECMAScript 5 or later */function Constructor() {}Constructor.prototype = x;return Object.getPrototypeOf(new Constructor()) === x;}
// https://stackoverflow.com/a/8511332/860099function H(x) {return typeof x === 'object' && x !== null}
// https://stackoverflow.com/a/25715455/860099function I(x) {return (typeof x === "object" && !Array.isArray(x) && x !== null);};
// https://stackoverflow.com/a/22482737/860099function J(x) {return x instanceof Object;}
// https://stackoverflow.com/a/50712057/860099function K(x){let t= JSON.stringify(x);return t ? t[0] === '{' : false;}
// https://stackoverflow.com/a/13356338/860099function L(x) {return Object.prototype.toString.call(x) === "[object Object]";};


// https://stackoverflow.com/a/46663081/860099function 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';let r;if (strict === true) {r = (instanceOfObject || typeOfObject) && (constructorUndefined || constructorObject);} else {r = (constructorUndefined || typeOfConstructorObject);}return r;}
// https://stackoverflow.com/a/42250981/860099function N(x) {return $.type(x) === 'object';}
// https://stackoverflow.com/a/34864175/860099function O(x) {if (Object.prototype.toString.call(x) !== '[object Object]') {return false;} else {var prototype = Object.getPrototypeOf(x);return prototype === null || prototype === Object.prototype;}}
// https://stackoverflow.com/a/57863169/860099function P(x) {while (     Object.prototype.toString.call(x) === '[object Object]')if    ((x = Object.getPrototypeOf(x))         === null)return truereturn false}
// https://stackoverflow.com/a/43289971/860099function Q(x){try{switch(x.constructor){case Number:case Function:case Boolean:case Symbol:case Date:case String:case RegExp:return x.constructor === Object;case Error:case EvalError:case RangeError:case ReferenceError:case SyntaxError:case TypeError:case URIError:return (Object === Error ? Error : x.constructor) === Object;case Array:case Int8Array:case Uint8Array:case Uint8ClampedArray:case Int16Array:case Uint16Array:case Int32Array:case Uint32Array:case Float32Array:case Float64Array:return (Object === Array ? Array : x.constructor) === Object;case Object:default:return (Object === Object ? Object : x.constructor) === Object;}} catch(ex){return x == Object;}}
// https://stackoverflow.com/a/52478680/860099function R(x) {return typeof x == 'object' && x instanceof Object && !(x instanceof Array);}
// https://stackoverflow.com/a/51458052/860099function S(x){return x != null && x.constructor?.name === "Object"}
// https://stackoverflow.com/a/42250981/860099function T(x) {return x?.constructor?.toString().indexOf("Object") > -1;}
// https://stackoverflow.com/a/43223661/860099function U(x){return x?.constructor === Object;}
// https://stackoverflow.com/a/46663081/860099function V(x) {return x instanceof Object && x.constructor === Object;}



// -------------// TEST// -------------
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(`Columns legend (test cases):1: new Date()2: /./ (RegExp)3: {}4: Object.prototype5: Object.create(null)6: ()=>{} (function)7: "abc" (string)8: 3 (number)9: true (boolean)10: null11: undefined
Rows:1 = is object0 = is NOT object
Theoretically columns 1-6 should have have 1, columns 7-11 shoud have 0`);
<scriptsrc="https://code.jquery.com/jquery-3.5.1.min.js"integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0="crossorigin="anonymous"></script>  
<scriptsrc="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.20/lodash.min.js"integrity="sha512-90vH1Z83AJY9DmlWa8WkjkV79yfS2n2Oxhsi2dZbIv0nC4E6m5AbH8Nh156kkM7JePmqD6tcZsfad1ueoaovww=="crossorigin="anonymous"></script>  
This shippet only presents functions used in performance tests - it not perform tests itself!

以下是chrome的示例结果

在此处输入图片描述

记住,typeof new Date()就是"object"

第一:评估对象的类型

第二:从Object获取Array属性必须返回undefined(例如length是对Object不起作用的Array属性)

所以:

if (_object instanceof Object && _object.length === undefined) {// here you can be sure that you have a curly bracket object :)}

这很棘手,因为数组是对象类型,函数是对象类型,实际对象{}也是对象类型

问题

const arr = []const fun = function(){}const actualObj = {}
arr instanceof Object // truefun instanceof Object // trueactualObj instanceof Object // true

所以目标实际上是Obj必须返回true,其他一切都必须返回false

actualObj instanceof Object && !(actualObj instanceof Array) && !(typeof actualObj === 'function') // true

简单的工作解决方案:

function isObject(value) {return !(value instanceof Date) && !Array.isArray(value) && !Object.is(value, null) && !Object.is(value, undefined) && !(value instanceof Function)}

我们只能用一行来检查这个,这里obj可以是任何值(包括null)

obj?.__proto__ === Object.prototype

obj?.constructor.name === 'Object';

我认为有这么多答案的原因是,无论你喜欢与否,JavaScript中的很多东西都是object

您可以像任何其他对象一样遍历数组的“键”…

var key,arr = ['one', 'two', 'three'];for (key in arr)console.log(`${key}=${arr[key]}`);
console.log(arr[1]);console.log(arr['1']);
// 0=one// 1=two// 2=three// two// two

数组是特殊的(像许多对象一样),因为它具有一些泛型Object没有的属性/方法(例如lengthforEach等)。

所以这个问题应该是:如何过滤特定类型的对象?

毕竟,我可以很容易地实现我自己的数组或正则表达式或符号,它也将是一个对象,但可能会通过所有各种“它是一个真实的对象吗?”测试……因为它是一个真实的对象。

所以你想过滤到某些类型的javascript对象…

最好的方法是只做功能测试。例如,你关心它是否有length属性吗?示例:浏览器中的NodeList看起来像一个数组,可以像数组一样迭代,但不是数组。

无论如何,如果你只是想过滤掉特定类型的对象,只有你可以定义你想要过滤的内容。你想过滤掉RegExp吗?日期?数组?浏览器DOM对象?只有你可以决定你的过滤器链是什么样子。您可以使用降级开关来紧凑地构建过滤器。

function typeOfIs(val, type) {return typeof val == type;}
function constructorIs(val, constructor) {return val && constructor && val.constructor === constructor;}
function isObject(val) {// catch the easy non-object valuesif (!typeOfIs(val, 'object'))return false;
// catch the cases you don't want to consider to be// "real" objects for your use-caseswitch (true) {case val === null:case Array.isArray(val):case typeOfIs(val, 'function'):case constructorIs(val, RegExp):return false;default:return true;}}function test(val) {console.log(Object.prototype.toString.call(val)+': '+isObject(val));}test(undefined);test(null);test(function () {});test(Symbol('foo'));test(1);test(true);test(false);test('hello world');test([]);test(/.*/g);test(new Date()); // true (because we didn't filter for it)test({});  // true

功能测试

不过,更好的做法可能是问你为什么要过滤,也许只是测试你需要/期望的属性/函数是否存在于给定变量上……如果存在,使用变量,不要担心它是某种类型的对象还是另一种。如果它们不存在,那么只需抛出一个API错误,表明你传递了一些不属于正确类型的值(即缺少预期的属性/函数)。

e. g.

if (typeof someVariable.hasOwnProperty == 'function')// ...

通过逆向选择的不同方法:

我在这里查看了所有答案,仍然缺少不同的方法。根据MDN文档,JavaScript中的对象是非原始值。原始值:

  1. 布尔类型
  2. 空类型
  3. 未定义类型
  4. 数字类型
  5. BigInt类型
  6. 字符串类型
  7. 符号类型

基于这一事实,以下方法正在实行逆向选择:

// Check if value is primitive value according to MDN docs:function isPrimitiveValue(value) {return (typeof value === "symbol" ||typeof value === "string" ||typeof value === "number" ||typeof value === "boolean" ||typeof value === "undefined" ||value === null ||typeof value === "bigint");};
// Check if input is not primitive value, therefore object:function isObject(input) {if (isPrimitiveValue(input)) {return false;}return true;};    
console.log(isObject(10)); // falseconsole.log(isObject([{foo: "bar"}])); // trueconsole.log(isObject({ a: 1, b: 2, c: 3 })); // trueconsole.log(isObject(Object.getPrototypeOf("foo"))); // trueconsole.log(isObject(Symbol("foo"))); // falseconsole.log(isObject(BigInt(9007199254740991))); // falseconsole.log(isObject(null)); // falseconsole.log(isObject(undefined)); // falseconsole.log(isObject(false)); // falseconsole.log(isObject({})); // true

适用于所有数据类型。它只显示对象

if (data && typeof data === 'object' && !Array.isArray(data)) {