你如何检查一个值是否是 JavaScript 中的一个对象?
49 回答
如果typeof yourVariable === 'object'
,它是一个对象或null
。
如果您想null
排除数组或函数,只需:
if (
typeof yourVariable === 'object' &&
!Array.isArray(yourVariable) &&
yourVariable !== null
) {
executeSomeCode();
}
更新:
这个答案是不完整的,并给出了误导性的结果。例如,在 JavaScriptnull
中也被认为是类型object
,更不用说其他几个边缘情况了。按照下面的建议,继续其他“最受好评(和正确!)的答案”:
typeof yourVariable === 'object' && yourVariable !== null
原始答案:
尝试使用typeof(var)
和/或var instanceof something
.
编辑:这个答案给出了如何检查变量属性的想法,但它不是一个防弹配方(毕竟根本没有配方!)用于检查它是否是一个远离它的对象。由于人们倾向于在不做任何研究的情况下从这里寻找要复制的东西,我强烈建议他们转向另一个,最受支持(和正确!)的答案。
让我们在 Javascript 中定义“对象”。根据MDN 文档,每个值要么是对象,要么是原语:
原始的,原始的价值
不是对象且没有任何方法的数据。JavaScript 有 7 种原始数据类型:string、number、bigint、boolean、undefined、symbol 和 null。
什么是原始人?
3
'abc'
true
null
undefined
什么是对象(即不是原语)?
Object.prototype
- 一切都起源于
Object.prototype
Function.prototype
Object
Function
function C(){}
-- 用户自定义函数
C.prototype
-- 用户定义函数的原型属性:这不是C
原型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)) -> 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 文档:
Object 构造函数为给定值创建一个对象包装器。如果值为 null 或未定义,它将创建并返回一个空对象,否则,它将返回一个与给定值对应的类型的对象。如果该值已经是一个对象,它将返回该值。
第三种似乎可行的方法(不确定它是否为 100%)是使用Object.getPrototypeOf
which如果其参数不是对象则抛出异常:
// 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({})
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;
};
Object.prototype.toString.call(myVar)
将返回:
"[object Object]"
如果 myVar 是一个对象"[object Array]"
如果 myVar 是一个数组- 等等
有关这方面的更多信息以及为什么它是 typeof 的一个很好的替代品,请查看这篇文章。
用于简单地检查对象或数组而无需额外的函数调用(速度)。也张贴在这里。
是数组()
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
我喜欢简单的:
function isObject (item) {
return (typeof item === "object" && !Array.isArray(item) && item !== null);
}
如果 item 是一个 JS 对象,并且它不是一个 JS 数组,而且它不是null
……如果这三个都证明是真的,则 return true
。如果三个条件中的任何一个失败,&&
测试将短路并false
返回。如果需要,可以省略该null
测试(取决于您的使用方式null
)。
文档:
http://devdocs.io/javascript/operators/typeof
http://devdocs.io/javascript/global_objects/object
带功能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
结果,您将拥有严格而健壮的代码!
如果您不会创建 , , 等函数isDate
,isError
您isRegExp
可以考虑使用此通用函数:
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 上已经创建了包!它适用于所有前面描述的测试用例!
我的天啊!我认为这可能比以往任何时候都短,让我们看看:
短代码和最终代码
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
解释
返回类型
typeof 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/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/name#Browser_compatibility
这取决于您对“是一个对象”的含义。如果你想要所有不是原始的东西,即你可以设置新属性的东西,这应该可以解决问题:
function isAnyObject(value) {
return value != null && (typeof value === 'object' || typeof value === 'function');
}
它不包括原语(纯数字/ NaN
/ Infinity
、纯字符串、符号、/true
和) ,但应为其他所有内容(包括、和对象)返回 true。请注意,JS 没有定义与 一起使用时应该返回的“宿主”对象,例如or ,因此很难用这样的检查来覆盖这些对象。false
undefined
null
Number
Boolean
String
window
console
typeof
如果您想知道某物是否是“普通”对象,即它是作为文字创建的{}
还是 with 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 中纯对象的定义。
好的,在回答你的问题之前,让我们先给你这个概念,在 JavaScript 中,函数是对象,还有 null、对象、数组甚至日期,所以你看到没有像 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);
我的上帝,其他答案太混乱了。
简答
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。
检查值类型的最合理方法似乎是typeof
运算符。唯一的问题是它被严重破坏了:
- 它返回
"object"
fornull
,属于 Null 类型。 - 它返回
"function"
属于 Object 类型的可调用对象。 - 它可以(几乎)为非标准的不可调用对象返回任何它想要的东西。例如,IE 似乎喜欢
"unknown"
. 唯一禁止的结果是"function"
原始类型。
typeof
仅对非null
基元可靠。因此,检查值是否为对象的一种方法是确保返回的字符串typeof
不对应于原语,并且该对象不是null
. 然而,问题是未来的标准可能会引入新的原始类型,而我们的代码会将其视为对象。新类型不经常出现,但例如 ECMAScript 6 引入了 Symbol 类型。
因此,typeof
我只推荐其结果取决于值是否为对象的方法,而不是 。以下打算成为
测试值是否属于 Object 类型的正确方法的全面但不详尽的列表。
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.create
需要Object.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
语句中以捕获错误。一些隐藏的例子,不值得评论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
而不直接访问它。
有点晚了......对于“普通对象”(我的意思是,像 {'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”。:)
这是一个带有可选链接的答案,也许是isObj
这个问题的最小函数。
const isObj = o => o?.constructor === Object;
// True for this
console.log(isObj({})); // object!
// False for these
console.log(isObj(0)); // number
console.log(isObj([])); // array
console.log(isObj('lol')); // string
console.log(isObj(null)); // null
console.log(isObj(undefined)); // undefined
console.log(isObj(() => {})); // function
console.log(isObj(Object)); // class
试试这个
if (objectName instanceof Object == false) {
alert('Not an object');
}
else {
alert('An object');
}
准备使用检查功能
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
sfunction
都是对象。虽然,null
有点做作。因此,最好检查第null
一个,以检测它不为空。检查作为对象的
typeof o === 'object'
保证o
。没有这个检查,Object.prototype.toString
将毫无意义,因为它会返回对象,甚至是undefined
和null
!例如:toString(undefined)
退货[object Undefined]
!经过
typeof o === 'object'
检查, toString.call(o) 是一个很好的方法来检查是否o
是一个对象,一个派生对象,如Array
,Date
还是一个function
.在
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));
}
// 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(){})
);
如果您想检查prototype
for an是否object
仅来自Object
. 过滤掉String
, Number
, Array
,Arguments
等
function isObject (n) {
return Object.prototype.toString.call(n) === '[object Object]';
}
或作为单表达式箭头函数 (ES6+)
const isObject = n => Object.prototype.toString.call(n) === '[object Object]'
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
}
lodash 有isPlainObject,这可能是许多来到这个页面的人正在寻找的东西。给出函数或数组时返回 false。
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"
在阅读并尝试了很多实现之后,我注意到很少有人尝试检查诸如JSON
、或原型链长于 1 步的对象之类Math
的值。document
而不是检查typeof
我们的变量然后破解边缘情况,我认为如果检查保持尽可能简单以避免在添加新的原语或本机对象注册为typeof
'object'时必须重构会更好'。
毕竟,typeof
运算符会告诉您某物是否是 JavaScript 的对象,但 JavaScript 对对象的定义对于大多数现实世界的场景(例如typeof null === 'object'
)来说过于宽泛。v
下面是一个通过重复两次检查来确定变量是否为对象的函数:
- 只要 is 的字符串化版本,就会开始一个
v
循环'[object Object]'
。
我希望函数的结果与下面的日志完全一样,所以这是我最终得到的唯一“对象性”标准。如果失败,该函数立即返回 false。 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'}))))
表现
今天 2020.09.26 我在 Chrome v85、Safari v13.1.2 和 Firefox v80 上针对所选解决方案在 MacOs HighSierra 10.13.6 上执行测试。
结果
- 解决方案 C 和 H 在所有情况下在所有浏览器上都是最快/最快的
- 对于所有情况,解决方案 D 和 G 在所有浏览器上都是最慢/最慢的
细节
我为解决方案A B C D E F G H I J K L M N O P Q R S T U V执行 3 个测试用例
下面的代码片段展示了解决方案之间的差异。Solutions AG 为Matt Fenwick描述的选定案例提供了正确的答案
// https://stackoverflow.com/a/14706877/860099
function A(x) {
return x === Object(x);
};
// https://stackoverflow.com/a/42250981/860099
function 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
function E(x) {
return function() { return this === x; }.call(x);
}
// https://stackoverflow.com/a/39187058/860099
function F(x) { /* Requires ECMAScript 5 or later */
try {
Object.create(x);
return x !== null;
} catch(err) {
return false;
}
}
// https://stackoverflow.com/a/39187058/860099
function G(x) { /* Requires ECMAScript 5 or later */
function Constructor() {}
Constructor.prototype = x;
return 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
function 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
function K(x)
{
let t= JSON.stringify(x);
return 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';
let r;
if (strict === true) {
r = (instanceOfObject || typeOfObject) && (constructorUndefined || constructorObject);
} else {
r = (constructorUndefined || typeOfConstructorObject);
}
return r;
}
// https://stackoverflow.com/a/42250981/860099
function N(x) {
return $.type(x) === 'object';
}
// https://stackoverflow.com/a/34864175/860099
function 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/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 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/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
function 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;
}
// -------------
// 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.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
Theoretically columns 1-6 should have have 1, columns 7-11 shoud have 0
`);
<script
src="https://code.jquery.com/jquery-3.5.1.min.js"
integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0="
crossorigin="anonymous"></script>
<script
src="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 的示例结果
当其他一切都失败时,我使用这个:
var isObject = function(item) {
return item.constructor.name === "Object";
};
这将起作用。它是一个返回 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 美分(这个答案是符合规范的,并且在所有情况下都会产生正确的结果):
原语测试:
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];
}
}());
出于我的代码的目的,我发现这个决定与上面的一些答案相对应:
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'; // true
checkType({}) === 'object'; // true
checkType(1) === 'number'; // true
checkType('') === 'string'; // true
checkType({}.p) === 'undefined'; // true
checkType(null) === 'null'; // true
等等..
const isObject = function(obj) {
const type = typeof obj;
return type === 'function' || type === 'object' && !!obj;
};
!!obj
是检查是否obj
为真(过滤掉null
)的简写
这是一个老问题,但想把它留在这里。大多数人正在检查变量是否{}
意味着键值配对,而不是 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 返回的数据库调用。然后我们可以测试 if is not an Array
, is not null
, is not typeof 'function'
, and is anObject
// 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
function isObjectLike(value) {
return value != null && typeof value == 'object' && !Array.isArray(value);
}
基于lodash
if(typeof value === 'object' && value.constructor === Object)
{
console.log("This is an object");
}
如果明确要检查给定值是否为{}
.
function isObject (value) {
return value && typeof value === 'object' && value.constructor === Object;
}
我从这个 SO 问题中找到了一种“新”方法来进行这种类型检查:Why does instanceof return false for some literals?
由此,我创建了一个类型检查函数,如下所示:
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 上测试的
编辑:
如果您还想检查变量是否为空或未定义,您可以使用它来代替:
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
我喜欢用的是这个
function isObject (obj) {
return typeof(obj) == "object"
&& !Array.isArray(obj)
&& obj != null
&& obj != ""
&& !(obj instanceof String) }
我认为在大多数情况下,日期必须作为对象通过检查,所以我不会过滤掉日期
你可以用它JSON.stringify
来测试你的对象,像这样:
var test = {}
if(JSON.stringify(test)[0] === '{') {
console.log('this is a Object')
}
如果你已经在使用 AngularJS,那么它有一个内置的方法来检查它是否是一个对象(不接受 null)。
angular.isObject(...)
考虑 -typeof bar === "object"
确定是否bar
是一个对象
尽管typeof bar === "object"
是检查 bar 是否为对象的可靠方法,但 JavaScript 中令人惊讶的问题是 null 也被视为对象!
因此,令大多数开发人员惊讶的是,以下代码会将 true(而非 false)记录到控制台:
var bar = null;
console.log(typeof bar === "object"); // logs true!
只要意识到这一点,就可以通过检查 bar 是否为空来轻松避免该问题:
console.log((bar !== null) && (typeof bar === "object")); // logs false
为了在我们的回答中完全彻底,还有两件事值得注意:
首先,如果 bar 是一个函数,上述解决方案将返回 false。在大多数情况下,这是所需的行为,但在您希望函数也返回 true 的情况下,您可以将上述解决方案修改为:
console.log((bar !== null) && ((typeof bar === "object") || (typeof bar === "function")));
var bar = [];
其次,如果 bar 是一个数组(例如 if )
,上述解决方案将返回 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 使数组 case 变得非常简单,包括它自己的 null 检查:
console.log(Array.isArray(bar));
确定变量是否为对象的最简单方法:
第一:评估Object的类型
第二:从 Object 获取 Array 属性必须返回undefined
(例如length
,Array 属性不适用于 Object)
所以:
if (_object instanceof Object && _object.length === undefined) {
// here you can be sure that you have a curly bracket object :)
}
它取决于用例,如果我们不想让数组和函数成为对象,我们可以使用 underscore.js 内置函数。
function xyz (obj) {
if (_.isObject(obj) && !_.isFunction(obj) && !_.isArray(obj)) {
// now its sure that obj is an object
}
}
大多数typeof obj[index] === 'object'
情况下使用,但它也会返回function
并且#document
哪些是对象。这取决于您是否需要将其包含在结果中。
基本上,您可以执行测试代码,通过检查控制台中的输出来过滤特定元素是否为对象。在这里,您可以运行代码仅作为示例:
function cekObject(obj, index) {
if (!obj.tagName) {
//test case #1
if (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>
这很棘手,因为数组是对象类型,函数是对象类型,而实际的对象 {} 也是对象类型
问题
const arr = []
const fun = function(){}
const actualObj = {}
arr instanceof Object // true
fun instanceof Object // true
actualObj instanceof Object // true
所以目标是actualObj必须返回true,其他一切都必须返回false
actualObj instanceof Object && !(actualObj instanceof Array) && !(typeof actualObj === 'function') // true
usetypeof(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]))
}
}
记住,伙计typeof new Date()
们"object"
。
因此,如果您正在寻找{ key: value }
对象,日期对象是无效的。
最后:o => o && typeof o === 'object' && !(o instanceof Date)
在我看来,这是对您问题的更好回答。
简单的工作解决方案:
function isObject(value) {
return !(value instanceof Date) && !Array.isArray(value) && !Object.is(value, null) && !Object.is(value, undefined) && !(value instanceof Function)
}
基于阅读 Matt Fenwick 的第三个选项到他上面的完整答案的一个小的 NodeJS 控制台实验。只需稍作调整即可获得true
or false
。
以下为对象测试返回 false。
> if(Object.getPrototypeOf('v') === Object.prototype){console.log(true);}else{console.log(false);}
false
undefined
> if(Object.getPrototypeOf(1) === Object.prototype){console.log(true);}else{console.log(false);}
false
undefined
> if(Object.getPrototypeOf(false) === Object.prototype){console.log(true);}else{console.log(false);}
false
undefined
> if(Object.getPrototypeOf(['apple']) === Object.prototype){console.log(true);}else{console.log(false);}
false
undefined
该对象将返回 true。
> if(Object.getPrototypeOf({'this':10}) === Object.prototype){console.log(true);}else{console.log(false);}
true
undefined
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));//true
console.log(Object.prototype.toString.call(_val)==='[object Object]');//false
直接回答当然是typeof v==='object'
,但这非常没有用。我想知道OP是否意味着一本普通的字典..
尝试:
isdict(v) { return v !== undefined && v!==null && typeof v==='object' && v.constructor!==Array && v.constructor!==Date; }
您可以使用Object.prototype的toString()方法轻松完成此操作
if(Object.prototype.toString.call(variable) == "[object Object]"){
doSomething();
}
或者
if(Object.prototype.toString.call(variable).slice(8,-1).toLowerCase() == "object"){
doSomething();
}
我有一个有效的代码片段。当没有给出整段代码时,我觉得很困惑,所以我自己创建了它:
<!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');
else
alert('abc is not an object');
}
</script>
</body>
</html>