你如何检查一个值是否是 JavaScript 中的一个对象?
null
是否是对象)。
如果是 typeof yourVariable === 'object'
,它是一个对象或 null
。
如果您想排除 null
、数组或函数,只需:
if (
typeof yourVariable === 'object' &&
!Array.isArray(yourVariable) &&
yourVariable !== null
) {
executeSomeCode();
}
更新:
此答案不完整,并提供误导性结果。例如,null
在 JavaScript 中也被认为是 object
类型,更不用说其他几种边缘情况了。遵循以下建议,然后转到其他 "most upvoted (and correct!) answer":
typeof yourVariable === 'object' && yourVariable !== null
原答案:
尝试使用 typeof(var)
和/或 var instanceof something
。
编辑:这个答案给出了如何检查变量属性的想法,但它不是一个防弹配方(毕竟根本没有配方!)用于检查它是否是一个远离它的对象。由于人们倾向于在不做任何研究的情况下从这里寻找要复制的东西,我强烈建议他们转向另一个,最受支持(和正确!)的答案。
typeof
为 null 返回“object”,它不是对象,并且 instanceof
不适用于使用 Object.create(null)
创建的对象。
typeof null
...object
!
someArray instanceof Object //true
或 typeof someArray === 'object' // true
。如果您尝试检测数组,那么:Object.prototype.toString.call(someObject) === "[object Object]"
或 "[object Array]"
怎么样?
让我们在 Javascript 中定义“对象”。根据 MDN docs,每个值要么是对象,要么是原语:
原始,原始值 不是对象且没有任何方法的数据。 JavaScript 有 7 种原始数据类型:string、number、bigint、boolean、undefined、symbol 和 null。
什么是原始人?
3
'ABC'
真的
无效的
不明确的
什么是对象(即不是原语)?
对象.原型
一切都源自 Object.prototype Function.prototype Object Function function C(){} -- 用户自定义函数 C.prototype -- 用户自定义函数的原型属性:这不是 Cs 原型 new C() -- " new"-ing 一个用户定义的函数 Math Array.prototype arrays {"a": 1, "b": 2} -- 使用文字符号创建的对象 new Number(3) -- 原语的包装器......许多其他的东西...
Function.prototype Object Function function C(){} -- 用户自定义函数
目的
功能
function C(){} -- 用户定义的函数
C.prototype -- 用户定义函数的原型属性:这不是 Cs 原型 new C() -- "new"-ing 用户定义函数
new C() -- "new"-ing 一个用户定义的函数
数学
Array.prototype 数组
数组
{"a": 1, "b": 2} -- 使用文字符号创建的对象
new Number(3) -- 原语的包装器
...许多其他事情...
对象.create(null)
一切都源于 Object.create(null)
如何检查一个值是否是一个对象
instanceof
本身不起作用,因为它错过了两种情况:
// oops: isObject(Object.prototype) -> false
// oops: isObject(Object.create(null)) -> false
function isObject(val) {
return val instanceof Object;
}
typeof x === 'object'
不起作用,因为误报 (null
) 和误报(函数):
// oops: isObject(Object) -> false
function isObject(val) {
return (typeof val === 'object');
}
Object.prototype.toString.call
不起作用,因为所有原语都存在误报:
> Object.prototype.toString.call(3)
"[object Number]"
> Object.prototype.toString.call(new Number(3))
"[object Number]"
所以我使用:
function isObject(val) {
if (val === null) { return false;}
return ( (typeof val === 'function') || (typeof val === 'object') );
}
@Daan 的回答似乎也有效:
function isObject(obj) {
return obj === Object(obj);
}
因为,根据 MDN docs:
Object 构造函数为给定值创建一个对象包装器。如果值为 null 或未定义,它将创建并返回一个空对象,否则,它将返回一个与给定值对应的类型的对象。如果该值已经是一个对象,它将返回该值。
第三种似乎可行的方法(不确定它是否为 100%)是使用 Object.getPrototypeOf
which throws an exception 如果其参数不是对象:
// these 5 examples throw exceptions
Object.getPrototypeOf(null)
Object.getPrototypeOf(undefined)
Object.getPrototypeOf(3)
Object.getPrototypeOf('abc')
Object.getPrototypeOf(true)
// these 5 examples don't throw exceptions
Object.getPrototypeOf(Object)
Object.getPrototypeOf(Object.prototype)
Object.getPrototypeOf(Object.create(null))
Object.getPrototypeOf([])
Object.getPrototypeOf({})
obj === Object(obj)
为数组返回 true
。
var x = []; console.log(x === Object(x)); // return true
getPrototypeOf
不适用于例如已撤销的代理,这些代理是对象但会抛出。
({}).toString.apply(obj) === '[object Object]'
这区分数组和不是数组的对象
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;
};
return obj === Object(obj) && Object.prototype.toString.call(obj) !== '[object Array]'
null
。应该是公认的答案。
Object.prototype.toString.call(myVar)
将返回:
"[object Object]" 如果 myVar 是一个对象
"[object Array]" 如果 myVar 是一个数组
等等
有关这方面的更多信息以及为什么它是 typeof 的良好替代品,check out this article。
typeof [] === 'object'
--> true
。这就是你需要的这个方法。
Object.prototype.toString.call(3)
-> "[object Number]"
。 Object.prototype.toString.call(new Number(3))
-> "[object Number]
"
getType=function(obj){return Object.prototype.toString.call(obj).match(/\[object (\w+)\]/)[1];};
用于简单地检查对象或数组而无需额外的函数调用(速度)。还发布了 here。
是数组()
isArray = function(a) {
return (!!a) && (a.constructor === Array);
};
console.log(isArray( )); // false
console.log(isArray( null)); // false
console.log(isArray( true)); // false
console.log(isArray( 1)); // false
console.log(isArray( 'str')); // false
console.log(isArray( {})); // false
console.log(isArray(new Date)); // false
console.log(isArray( [])); // true
isLiteralObject() - 注意:仅用于 Object 字面量,因为它为自定义对象返回 false,例如 new Date 或 new YourCustomObject。
isLiteralObject = function(a) {
return (!!a) && (a.constructor === Object);
};
console.log(isLiteralObject( )); // false
console.log(isLiteralObject( null)); // false
console.log(isLiteralObject( true)); // false
console.log(isLiteralObject( 1)); // false
console.log(isLiteralObject( 'str')); // false
console.log(isLiteralObject( [])); // false
console.log(isLiteralObject(new Date)); // false
console.log(isLiteralObject( {})); // true
{
字符开头的东西。对于数组的情况,只要不需要支持IE < 9、你可以使用Array.isArray()
来判断某个东西是否是一个数组。它通过了您提供的所有测试用例。
!!a
isObject(null)
将返回 null
而不是 false
我喜欢简单的:
function isObject (item) {
return (typeof item === "object" && !Array.isArray(item) && item !== null);
}
如果该项目是一个 JS 对象,并且它不是一个 JS 数组,并且它不是 null
……如果这三个都为真,则返回 true
。如果三个条件中的任何一个失败,&&
测试将短路并返回 false
。如果需要,可以省略 null
测试(取决于您如何使用 null
)。
文档:
http://devdocs.io/javascript/operators/typeof
http://devdocs.io/javascript/global_objects/object
http://devdocs.io/javascript/global_objects/array/isarray
http://devdocs.io/javascript/global_objects/null
new Date()
返回一个对象。从逻辑的角度来看,数组不是对象——尽管 JavaScript 会处理和报告它们。然而,在实践中,看到它们相等是没有帮助的,因为它们不是。例如,一个对象没有 length
属性,也没有 push() 之类的方法。有时你可能想给一个函数重载参数,你需要在数组或对象之间做出区别,特别是如果其他参数取决于给定的参数。
length
属性或 push
之类的方法,Object.create(Array.prototype)
是具有这些属性的非数组对象的一个微不足道的反例。数组的特别之处在于它们是具有自定义 [[DefineOwnProperty]] 基本内部方法的奇异对象,但它们仍然是对象。
length
属性(我的意思是对象文字默认没有 length
属性)。我写道,从 logical 的角度来看,数组不是对象。我说的是程序逻辑。有时需要检查一个数组是否是“真实”数组,而绝对不是“真实”对象。这就是 Array.isArray()
的用途。想象一下,您有一个接受对象或对象数组的函数。检查特殊属性或方法是一个肮脏的解决方案。原生方式总是更好。
typeof null
是 "object"
,而不是 "undefined"
。
使用函数 Array.isArray:
function isObject(o) {
return o !== null && typeof o === 'object' && Array.isArray(o) === false;
}
没有函数 Array.isArray:
只是惊讶于错误答案有多少赞 😮
只有 1 answer 通过了我的测试!!!在这里,我创建了我的简化版本:
function isObject(o) {
return o instanceof Object && o.constructor === Object;
}
至于我,它很清晰,很简单,而且很有效!这是我的测试:
console.log(isObject({})); // Will return: true
console.log(isObject([])); // Will return: false
console.log(isObject(null)); // Will return: false
console.log(isObject(/.*/)); // Will return: false
console.log(isObject(function () {})); // Will return: false
再一次:并非所有答案都通过了这个测试!!! 🙈
如果您需要验证该对象是特定类的实例,则必须使用特定类检查构造函数,例如:
function isDate(o) {
return o instanceof Object && o.constructor === Date;
}
简单测试:
var d = new Date();
console.log(isObject(d)); // Will return: false
console.log(isDate(d)); // Will return: true
结果,您将拥有严格而健壮的代码!
如果您不会创建 isDate
、isError
、isRegExp
等函数,您可以考虑使用此通用函数的选项:
function isObject(o) {
return o instanceof Object && typeof o.constructor === 'function';
}
它不适用于前面提到的所有测试用例,但对于所有对象(普通或构造)来说已经足够了。
isObject
在 Object.create(null)
的情况下不起作用,因为 Object.create
的内部实现已在 here 中解释,但您可以在更复杂的实现中使用 isObject
:
function isObject(o, strict = true) {
if (o === null || o === undefined) {
return false;
}
const instanceOfObject = o instanceof Object;
const typeOfObject = typeof o === 'object';
const constructorUndefined = o.constructor === undefined;
const constructorObject = o.constructor === Object;
const typeOfConstructorObject = typeof o.constructor === 'function';
let r;
if (strict === true) {
r = (instanceOfObject || typeOfObject) && (constructorUndefined || constructorObject);
} else {
r = (constructorUndefined || typeOfConstructorObject);
}
return r;
};
已经基于此实现创建了 package on npm v1!它适用于所有前面描述的测试用例! 🙂
isDate
用于 yourDateObject 以编写健壮的代码,否则您将拥有脆弱的 isObject
方法。
Date
是错误的选择,因为是的,答案确实讨论了 Date
。但 Date
只是无限可能的类之一,这一点适用于任何其他类。示例:class Foo() { }; var x = new Foo(); isObject(x)
返回 false
。我不确切知道 OP 的用例是什么,但很容易设想必须了解所有可能的类并专门针对每一个类进行检查的场景 将是不可行的。
我的天啊!我认为这可能比以往任何时候都短,让我们看看:
短代码和最终代码
function isObject(obj) { return obj != null && obj.constructor.name === "Object" } console.log(isObject({})) // 返回 true console.log(isObject([])) //返回 false console.log(isObject(null)) // 返回 false
解释
返回类型
typeof JavaScript 对象(包括 null
)返回 "object"
console.log(typeof null, typeof [], typeof {})
检查他们的构造函数
检查它们的 constructor
属性会返回带有它们名称的函数。
console.log(({}).constructor) // 返回一个名为“Object”的函数 console.log(([]).constructor) // 返回一个名为“Array”的函数 console.log((null). constructor) //抛出错误,因为 null 实际上没有属性
介绍 Function.name
Function.name
返回函数的只读名称或 "anonymous"
用于闭包。
console.log(({}).constructor.name) // 返回“对象” console.log(([]).constructor.name) // 返回“数组” console.log((null).constructor.name) //抛出错误,因为null实际上没有属性
注意:截至 2018 年,Function.name 可能无法在 IE 中使用 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/name#Browser_compatibility
Object.create(null)
以及为什么你会这样做......?
return obj != null && obj.constructor && obj.constructor.name === "Object"
条件“obj.constructor”返回 false,因为 Object.create(null) 创建了一个没有属性的对象,甚至没有 .__proto__ 或 .constructor。
const isObject = (obj) => (obj ?? false)?.constructor?.name === "Object";
谢谢!
好的,在回答你的问题之前,让我们先给你这个概念,在 JavaScript 中,函数是 Object,还有 null、Object、Arrays 甚至 Date,所以你看到没有像 typeof obj === 'object' 这样的简单方法,所以上面提到的所有内容都会返回 true,但是有一些方法可以通过编写函数或使用 JavaScript 框架来检查它,OK:
现在,假设您有这个对象是一个真实的对象(不是 null 或函数或数组):
var obj = {obj1: 'obj1', obj2: 'obj2'};
纯 JavaScript:
//that's how it gets checked in angular framework
function isObject(obj) {
return obj !== null && typeof obj === 'object';
}
或者
//make sure the second object is capitalised
function isObject(obj) {
return Object.prototype.toString.call(obj) === '[object Object]';
}
或者
function isObject(obj) {
return obj.constructor.toString().indexOf("Object") > -1;
}
或者
function isObject(obj) {
return obj instanceof Object;
}
您可以通过调用它们在代码中简单地使用上述函数之一,如果它是一个对象,它将返回 true:
isObject(obj);
如果你使用的是 JavaScript 框架,他们通常会为你准备好这些类型的函数,这些是其中的几个:
jQuery:
//It returns 'object' if real Object;
jQuery.type(obj);
角度:
angular.isObject(obj);
下划线和 Lodash:
//(NOTE: in Underscore and Lodash, functions, arrays return true as well but not null)
_.isObject(obj);
这取决于您对“是一个对象”的含义。如果你想要所有不是原始的东西,即你可以设置新属性的东西,这应该可以解决问题:
function isAnyObject(value) {
return value != null && (typeof value === 'object' || typeof value === 'function');
}
它不包括原语(纯数字/NaN
/Infinity
、纯字符串、符号、true
/false
、undefined
和 null
),但对于其他所有内容(包括 Number
、 Boolean
和 String
对象)。请注意,JS 没有定义与 typeof
一起使用时应返回的“主机”对象(例如 window
或 console
),因此很难用这样的检查来覆盖这些对象。
如果您想知道某物是否是“普通”对象,即它是作为文字 {}
还是使用 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 中纯对象的定义。
instanceof Object
,两个相同的函数字面量并不严格相等,它们是通过引用传递的,等等。
我的上帝,其他答案太混乱了。
简答
typeof anyVar == 'object' && anyVar instanceof Object && !(anyVar instanceof Array)
要对此进行测试,只需在 chrome 控制台中运行以下语句。
情况1。
var anyVar = {};
typeof anyVar == 'object' && anyVar instanceof Object && !(anyVar instanceof Array) // true
案例 2。
anyVar = [];
typeof anyVar == 'object' && anyVar instanceof Object && !(anyVar instanceof Array) // false
案例 3。
anyVar = null;
typeof anyVar == 'object' && anyVar instanceof Object && !(anyVar instanceof Array); // false
解释
好吧,让我们分解一下
typeof anyVar == 'object'
从三个候选者返回 true - [], {} and null
,
anyVar instanceof Object
将这些候选人缩小到两个 - [], {}
!(anyVar instanceof Array)
缩小到只有一个 - {}
请打鼓!
至此,您可能已经学会了如何在 Javascript 中检查 Array。
anyVar
是一个函数时,这也会返回 false
(根据需要)。
尝试这个
if (objectName instanceof Object) {
alert('Not an object');
}
else {
alert('An object');
}
Object.prototype instanceof Object
->错误的。 Object.create(null) instanceof Object
->错误的。
new Date() instanceof Object
=>真的
检查值类型的最合理方法是 typeof
运算符。唯一的问题是它被严重破坏了:
它返回 null 的“对象”,它属于 Null 类型。
它为属于 Object 类型的可调用对象返回“函数”。
它可以(几乎)为非标准的不可调用对象返回任何它想要的东西。例如,IE 似乎喜欢“未知”。唯一被禁止的结果是“函数”和原始类型。
typeof
仅对非 null
基元可靠。因此,检查一个值是否为对象的一种方法是确保 typeof
返回的字符串不对应于原语,并且该对象不是 null
。然而,问题是未来的标准可能会引入新的原始类型,而我们的代码会将其视为对象。新类型不经常出现,但例如 ECMAScript 6 引入了 Symbol 类型。
因此,我只推荐其结果取决于值是否为对象的方法,而不是 typeof
。以下打算成为
测试值是否属于 Object 类型的正确方法的全面但不详尽的列表。
Object 构造器 Object 构造器将传递的参数强制为对象。如果它已经是一个对象,则返回相同的对象。因此,您可以使用它将值强制转换为对象,并严格将该对象与原始值进行比较。以下函数需要 ECMAScript 3,它引入了 ===: function isObject(value) { /* 需要 ECMAScript 3 或更高版本 */ return Object(value) === value;我喜欢这种方法,因为它简单且具有自我描述性,并且类似的检查也适用于布尔值、数字和字符串。但是,请注意,它依赖于不被遮蔽或更改的全局对象。
构造函数 当你实例化一个构造函数时,它可以返回一个与刚刚创建的实例不同的值。但是除非它是一个对象,否则该值将被忽略。以下函数需要 ECMAScript 3,它允许构造函数返回非对象。在 ECMAScript 3 之前抛出错误,但当时不存在 try 语句。 function isObject(value) { /* 需要 ECMAScript 3 或更高版本 */ return new function() { return value; }() === 值;虽然比前面的例子简单一点,但这个例子不依赖于任何全局属性,因此可能是最安全的。
this value 旧的 ECMAScript 规范要求 this 值是一个对象。 ECMAScript 3 引入了 Function.prototype.call,它允许调用具有任意 this 值的函数,但被强制为对象。 ECMAScript 5 引入了一种严格模式来消除这种行为,但在草率模式下,我们仍然可以(但可以说不应该)依赖它。 function isObject(value) { /* 在草率模式下需要 ECMAScript 3 或更高版本 */ return function() { return this === value; }.call(值); }
[[Prototype]] 所有普通对象都有一个称为 [[Prototype]] 的内部槽,其值决定了它从哪个其他对象继承。该值只能是对象或空值。因此,您可以尝试创建一个从所需值继承的对象,并检查它是否有效。 Object.create 和 Object.getPrototypeOf 都需要 ECMAScript 5。 function isObject(value) { /* 需要 ECMAScript 5 或更高版本 */ try { Object.create(value);返回值 !== null; } 捕捉(错误){ 返回错误; } } function isObject(value) { /* 需要 ECMAScript 5 或更高版本 */ function Constructor() {} Constructor.prototype = value;返回 Object.getPrototypeOf(new Constructor()) === 值; }
一些新的 ECMAScript 6 方法 ECMAScript 6 引入了一些新的间接方法来检查值是对象。他们使用之前看到的方法将值传递给一些需要对象的代码,包裹在 try 语句中以捕获错误。一些隐藏的例子,不值一提 function isObject(value) { /* 需要 ECMAScript 6 或更高版本 */ try { Object.setPrototypeOf({}, value);返回值 !== null; } 捕捉(错误){ 返回错误; } } function isObject(value) { /* 需要 ECMAScript 6 或更高版本 */ try { new WeakSet([value]);返回真; } 捕捉(错误){ 返回错误; } }
注意:我有意跳过了一些方法,例如 Object.getPrototypeOf(value)
(ES5) 和 Reflect
方法 (ES6),因为它们调用了可能会做一些讨厌的事情的基本内部方法,例如,如果 value
是一个代理。出于安全原因,我的示例仅引用 value
而不直接访问它。
有点晚了......对于“普通对象”(我的意思是,像 {'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”。 :)
准备使用检查功能
function isObject(o) {
return null != o &&
typeof o === 'object' &&
Object.prototype.toString.call(o) === '[object Object]';
}
function isDerivedObject(o) {
return !isObject(o) &&
null != o &&
(typeof o === 'object' || typeof o === 'function') &&
/^\[object /.test(Object.prototype.toString.call(o));
}
// Loose equality operator (==) is intentionally used to check
// for undefined too
// Also note that, even null is an object, within isDerivedObject
// function we skip that and always return false for null
解释
在 Javascript 中,null、Object、Array、Date 和函数都是对象。虽然, null 有点做作。因此,最好先检查空值,以检测它不是空值。
检查 typeof o === 'object' 保证 o 是一个对象。如果没有这个检查,Object.prototype.toString 将毫无意义,因为它会返回任何东西的对象,即使是 undefined 和 null!例如:toString(undefined) 返回[object Undefined]!在 typeof o === 'object' 检查之后,toString.call(o) 是检查 o 是否为对象、派生对象(如 Array、Date 或函数)的好方法。
在 isDerivedObject 函数中,它检查 o 是否是一个函数。因为,函数也是一个对象,这就是它存在的原因。如果它没有这样做,函数将返回为假。示例:isDerivedObject(function() {}) 将返回 false,但现在它返回 true。
人们总是可以改变什么是对象的定义。因此,可以相应地更改这些功能。
测试
function isObject(o) { return null != o && typeof o === 'object' && Object.prototype.toString.call(o) === '[object Object]'; } function isDerivedObject(o) { return !isObject(o) && null != o && (typeof o === 'object' || typeof o === 'function') && /^\[object /.test(Object .prototype.toString.call(o)); } // 测试 // 是 null 一个对象吗? console.log( '是 null 一个对象吗?', isObject(null) ); console.log( '是 null 一个派生对象吗?', isDerivedObject(null) ); // 1234 是一个对象吗? console.log('1234 是一个对象吗?', isObject(1234) ); console.log( '1234 是派生对象吗?', isDerivedObject(1234) ); // new Number(1234) 是一个对象吗? console.log('new Number(1234) 是一个对象吗?', isObject(new Number(1234)) ); console.log( '新 Number(1234) 是派生对象吗?', isDerivedObject(1234) ); // 函数对象是对象吗? console.log( '是 (new (function (){})) 一个对象吗?', isObject((new (function (){}))) ); console.log( 'is (new (function (){})) 是派生对象吗?', isObject((new (function (){}))) ); // {} 是一个对象吗? console.log('是 {} 一个对象吗?', isObject({}) ); console.log( '是 {} 一个派生对象吗?', isDerivedObject({}) ); // 数组是对象吗? console.log( '数组是对象吗?', isObject([]) ) console.log( '数组是派生对象吗?', isDerivedObject([]) ) // Date 是对象吗? console.log('Date 是一个对象吗?', isObject(new Date())); console.log( 'Date 是派生对象吗?', isDerivedObject(new Date()) ); // 函数是对象吗? console.log( '函数是对象吗?', isObject(function(){}) ); console.log( '函数是派生对象吗?', isDerivedObject(function(){}) );
这是一个带有可选链接的答案,也许是这个问题的最小 isObj
函数。
const isObj = o => o?.constructor === Object; // 对于这个 console.log(isObj({})); // 目的! // 这些为 false console.log(isObj(0)); // 数字 console.log(isObj([])); // 数组 console.log(isObj('lol')); // 字符串 console.log(isObj(null)); // null console.log(isObj(undefined)); // 未定义的 console.log(isObj(() => {})); // 函数 console.log(isObj(Object)); // 班级
new Error()
在您的函数中将是错误的。
如果您想检查 object
的 prototype
是否仅来自 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]'
return Object.prototype.toString.call(n) === '[object Object]'
null
检查,因为 Object.prototype.toString.call(null) === '[object Null]'
var a = [1]
typeof a //"object"
a instanceof Object //true
a instanceof Array //true
var b ={a: 1}
b instanceof Object //true
b instanceof Array //false
var c = null
c instanceof Object //false
c instanceof Array //false
我被要求提供更多细节。检查我们的变量是否为对象的最简洁易懂的方法是 typeof myVar
。它返回一个带有类型的字符串(例如"object"
、"undefined"
)。
不幸的是,Array 和 null 也有一个类型 object
。要仅获取真实对象,需要使用 instanceof
运算符检查继承链。它将消除 null,但 Array 在继承链中有 Object。
所以解决方案是:
if (myVar instanceof Object && !(myVar instanceof Array)) {
// code for objects
}
/./ instanceof Object //true
表现
今天 2020.09.26 我在 Chrome v85、Safari v13.1.2 和 Firefox v80 上针对所选解决方案在 MacOs HighSierra 10.13.6 上执行测试。
结果
解决方案 C 和 H 在所有情况下在所有浏览器上都是最快/最快的
对于所有情况,解决方案 D 和 G 在所有浏览器上都是最慢/最慢的
https://i.stack.imgur.com/6zkbC.png
细节
我为解决方案执行 3 个测试用例 A B C D E F G H I J K L M N { 15} P Q R S T U V
对于小物体 - 你可以在这里运行它
对于大物体 - 你可以在这里运行它
没有对象 - 你可以在这里运行它
下面的代码片段展示了解决方案之间的差异。 Solutions AG 对 Matt Fenwick 所描述的选定案例给出了正确的答案
// https://stackoverflow.com/a/14706877/860099 函数 A(x) { return x === Object(x); }; // https://stackoverflow.com/a/42250981/860099 函数 B(x) { return _.isObject(x); } // https://stackoverflow.com/a/34864175/860099 function C(x) { return x != null && (typeof x === 'object' || typeof x === 'function'); } // https://stackoverflow.com/a/39187058/860099 function D(x) { return new function() { return x; }() === x; } // https://stackoverflow.com/a/39187058/860099 函数 E(x) { return function() { return this === x; }.call(x); } // https://stackoverflow.com/a/39187058/860099 function F(x) { /* 需要 ECMAScript 5 或更高版本 */ try { Object.create(x);返回 x !== null; } 捕捉(错误){ 返回错误; } } // https://stackoverflow.com/a/39187058/860099 function G(x) { /* 需要 ECMAScript 5 或更高版本 */ function Constructor() {} Constructor.prototype = x;返回 Object.getPrototypeOf(new Constructor()) === x; } // https://stackoverflow.com/a/8511332/860099 function H(x) { return typeof x === 'object' && x !== null } // https://stackoverflow.com/a/ 25715455/860099 函数 I(x) { return (typeof x === "object" && !Array.isArray(x) && x !== null); }; // https://stackoverflow.com/a/22482737/860099 function J(x) { return x instanceof Object; } // https://stackoverflow.com/a/50712057/860099 函数 K(x) { let t= JSON.stringify(x);返回 t ? t[0] === '{' : false; } // https://stackoverflow.com/a/13356338/860099 function L(x) { return Object.prototype.toString.call(x) === "[object Object]"; }; // https://stackoverflow.com/a/46663081/860099 function M(o, strict = true) { if (o === null || o === undefined) { return false; } const instanceOfObject = o instanceof Object; const typeOfObject = typeof o === 'object'; const constructorUndefined = o.constructor === undefined; const constructorObject = o.constructor === Object; const typeOfConstructorObject = typeof o.constructor === 'function';让 r; if (strict === true) { r = (instanceOfObject || typeOfObject) && (constructorUndefined || constructorObject); } else { r = (constructorUndefined || typeOfConstructorObject); } 返回 r; } // https://stackoverflow.com/a/42250981/860099 函数 N(x) { return $.type(x) === 'object'; } // https://stackoverflow.com/a/34864175/860099 函数 O(x) { if (Object.prototype.toString.call(x) !== '[object Object]') { return false; } else { var 原型 = Object.getPrototypeOf(x);返回原型 === null ||原型 === Object.prototype; } } // https://stackoverflow.com/a/57863169/860099 function P(x) { while ( Object.prototype.toString.call(x) === '[object Object]') if ((x = Object.getPrototypeOf(x)) === null) return true return false } // https://stackoverflow.com/a/43289971/860099 function Q(x){ try{ switch(x.constructor){ case Number: case 函数:case 布尔值:case 符号:case 日期:case 字符串:case RegExp:return x.constructor === Object;案例错误:案例EvalError:案例范围错误:案例参考错误:案例语法错误:案例类型错误:案例URIError:返回(对象===错误?错误:x.constructor)===对象;案例数组:案例Int8Array:案例Uint8Array:案例Uint8ClampedArray:案例Int16Array:案例Uint16Array:案例Int32Array:案例Uint32Array:案例Float32Array:案例Float64Array:返回(对象===数组?数组:x.constructor)===对象;案例对象:默认:返回(对象===对象?对象:x.constructor)===对象; } } catch(ex){ return x == Object; } } // https://stackoverflow.com/a/52478680/860099 function R(x) { return typeof x == 'object' && x instanceof Object && !(x instanceof Array); } // https://stackoverflow.com/a/51458052/860099 function S(x) { return x != null && x.constructor?.name === "Object" } // https://stackoverflow.com /a/42250981/860099 函数 T(x) { return x?.constructor?.toString().indexOf("Object") > -1; } // https://stackoverflow.com/a/43223661/860099 function U(x) { return x?.constructor === Object; } // https://stackoverflow.com/a/46663081/860099 function V(x) { return x instanceof Object && x.constructor === Object; } // ------------- // 测试 // ------------- console.log('column: 1 2 3 4 5 6 - 7 8 9 10 11'); [A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V] .map(f= > console.log(`${f.name}: ${1*f(new Date())} ${1*f(/./)} ${1*f({})} ${1* f(Object.prototype)} ${1*f(Object.create(null))} ${1*f(()=>{})} - ${1*f("abc")} ${1 *f(3)} ${1*f(true)} ${1*f(null)} ${1*f(undefined)}`)) console.log(` 列图例(测试用例):1: new Date() 2: /./ (RegExp) 3: {} 4: Object.prototype 5: Object.create(null) 6: ()=>{} (function) 7: "abc" (string) 8: 3 (number) 9: true (boolean) 10: null 11: undefined Rows: 1 = is object 0 = is NOT object 理论上第 1-6 列应该有 1,第 7-11 列应该有 0 `);
yourVariable !== null
会是更好的做法吗?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.
Object.prototype.toString.call(yourVar)
,作为您需要检查的 yourVar。如果是数组,Object.prototype.toString.call([1,2])
返回[object Array]
Array.isArray(yourVariable)
。