如何检查值是否是JavaScript中的对象?
当前回答
我喜欢用这个
function isObject (obj) {
return typeof(obj) == "object"
&& !Array.isArray(obj)
&& obj != null
&& obj != ""
&& !(obj instanceof String) }
我认为在大多数情况下,Date必须作为Object通过检查,因此我不会过滤掉日期
其他回答
这取决于你所说的“是一个物体”。如果您想要所有非原语的内容,即可以设置新财产的内容,那么这应该可以做到:
function isAnyObject(value) {
return value != null && (typeof value === 'object' || typeof value === 'function');
}
它排除了基元(纯数字/NaN/Infinity、纯字符串、符号、true/false、undefined和null),但其他所有对象(包括Number、Boolean和String对象)都应返回true。注意,JS没有定义当与typeof一起使用时,应该返回哪些“主机”对象,例如窗口或控制台,因此很难用这样的检查来覆盖这些对象。
如果您想知道某个对象是“普通”对象,即它是作为文本{}创建的还是使用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.protoct.toString.call(…)的输出,所以上面的isPlainObject函数在某些情况下可能会返回false,即使对象以文本形式开始其生命。可以说,按照惯例,带有自定义字符串标记的对象不再是纯对象,但这进一步模糊了Javascript中的纯对象定义。
在阅读并尝试了许多实现之后,我注意到很少有人尝试检查JSON、Math、文档或原型链长度超过1步的对象等值。
我认为,与其检查变量的类型,然后删除边缘事例,不如尽可能简单地进行检查,以避免在添加了注册为“对象”类型的新原语或本地对象时进行重构。
毕竟,typeof运算符会告诉您某个对象是否是JavaScript的对象,但JavaScript对对象的定义对于大多数真实场景来说太宽泛了(例如typeof null==“object”)。下面是一个函数,它通过基本上重复两次检查来确定变量v是否为对象:
只要v的字符串化版本为“[object object]”,就会启动一个循环。我希望函数的结果与下面的日志完全相同,所以这是我最终得出的唯一“对象性”标准。如果失败,函数将立即返回false。v被链中的下一个原型替换为v=Object.getPrototypeOf(v),但也在之后直接求值。当v的新值为null时,这意味着包括根原型(很可能是链中唯一的原型)在内的每个原型都通过了while循环中的检查,我们可以返回true。否则,新的迭代开始。
函数isObj(v){while(Object.product.toString.call(v)=='[Object Object]')if((v=Object.getPrototypeOf(v))==null)返回truereturn false}console.log('FALSE:')console.log('[]->',isObj([]))console.log('ull->',isObj(null))console.log('文档->',isObj(文档))console.log('JSON->',isObj(JSON))console.log('function->',isObj(函数(){}))console.log('newDate()->',isObj(newDate(()))console.log('RegExp->',isObj(/./))console.log('TRUE:')console.log(“{}->”,isObj({}))console.log('newObject()->',isObj(newObject(()))console.log('新对象(null)->',isObj(新对象(空)))console.log('newObject({})->',isObj(newObject({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继承->”,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在所有浏览器上都是慢/最慢的
细节
我为解决方案执行3个测试用例A.BCDEFGH我JKLMNOPQRSTU五、
对于小对象-您可以在此处运行对于大型对象-您可以在此处运行没有对象-你可以在这里运行
下面的代码片段介绍了解决方案之间的差异。解决方案A-G为Matt Fenwick描述的选定案例提供了正确的答案
// https://stackoverflow.com/a/14706877/860099函数A(x){return x===对象(x);};// https://stackoverflow.com/a/42250981/860099函数B(x){return _.isObject(x);}// https://stackoverflow.com/a/34864175/860099函数C(x){返回x!=null&&(typeof x===“对象”| | typeof x====“函数”);}// https://stackoverflow.com/a/39187058/860099函数D(x){return new函数(){return x;}()==x;}// https://stackoverflow.com/a/39187058/860099函数E(x){return函数(){return this==x;}.call(x);}// https://stackoverflow.com/a/39187058/860099函数F(x){/*需要ECMAScript 5或更高版本*/尝试{对象.create(x);返回x!==无效的}捕获(错误){return false;}}// https://stackoverflow.com/a/39187058/860099函数G(x){/*需要ECMAScript 5或更高版本*/函数构造函数(){}Constructor.prototype=x;return Object.getPrototypeOf(new Constructor())==x;}// https://stackoverflow.com/a/8511332/860099函数H(x){返回类型x=='对象'&&x!==无效的}// https://stackoverflow.com/a/25715455/860099函数I(x){return(typeof x==“object”&&!Array.isArray(x)&&x!==空);};// https://stackoverflow.com/a/22482737/860099函数J(x){return x instanceof Object;}// https://stackoverflow.com/a/50712057/860099函数K(x){设t=JSON.stringify(x);返回t?t[0]==“{”:false;}// https://stackoverflow.com/a/13356338/860099函数L(x){return Object.pr原型.toString.call(x)==“[对象对象]”;};// https://stackoverflow.com/a/46663081/860099函数M(o,strict=true){如果(o==null | | o==未定义){return false;}const instanceOfObject=o instanceof Object;const typeOfObject=typeof o==“对象”;constconstructorUndefined=o.constructor===未定义;constconstructorObject=o.constructor==对象;const typeOfConstructorObject=typeof o.constructor==“函数”;设r;if(严格==真){r=(instanceOfObject | | typeOfObject)&&(constructorUndefined | | constructorObject);}其他{r=(constructorUndefined | | typeOfConstructorObject);}返回r;}// https://stackoverflow.com/a/42250981/860099函数N(x){return$.type(x)==“对象”;}// https://stackoverflow.com/a/34864175/860099函数O(x){if(Object.pr原型.toString.call(x)!=='[object对象]'){return false;}其他{var prototype=对象.getPrototypeOf(x);返回原型==null | |原型==Object.prototype;}}// https://stackoverflow.com/a/57863169/860099函数P(x){while(Object.product.toString.call(x)=='[Object Object]')if((x=Object.getPrototypeOf(x))==null)返回truereturn false}// https://stackoverflow.com/a/43289971/860099函数Q(x){尝试{开关(x.constructor){案例编号:case函数:大小写布尔值:case符号:案例日期:case字符串:大小写RegExp:return x.constructor==对象;case错误:case评估错误:大小写范围错误:案例引用错误:case语法错误:案例类型错误:大小写URI错误:return(对象==错误?错误:x.constructor)==对象;case数组:大小写Int8Array:大小写Uint8Array:case Uint8ClampedArray:大小写Int16Array:大小写Uint16Array:case Int32Array:大小写Uint32Array:case Float32阵列:case浮点64Array:return(对象==数组?数组:x.constructor)==对象;case对象:违约:return(对象==对象?对象:x.constructor)==对象;}}捕获(ex){return x==对象;}}// https://stackoverflow.com/a/52478680/860099函数R(x){return typeof x=='对象'&&x对象实例&&!(数组的x实例);}// https://stackoverflow.com/a/51458052/860099函数S(x){返回x!=null&&x.constructor?。name==“对象”}// https://stackoverflow.com/a/42250981/860099函数T(x){返回x?。构造函数?。toString().indexOf(“对象”)>-1;}// https://stackoverflow.com/a/43223661/860099函数U(x){返回x?。构造函数==对象;}// https://stackoverflow.com/a/46663081/860099函数V(x){返回x对象实例&&x.constructor==对象;}// -------------//测试// -------------console.log('列: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 1*(true)}{1*(null)}$2 1*f(未定义)}`)))控制台日志(`列图例(测试用例):1:新日期()2: /./ (RegExp)3: {}4:对象.原型5:对象.create(null)6:()=>{}(函数)7:“abc”(字符串)8:3(数字)9:真(布尔值)10:空11:未定义排:1=是对象0=不是对象理论上,第1-6列应有1,第7-11列应有0`);<脚本src=“https://code.jquery.com/jquery-3.5.1.min.js"integrity=“sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphpj0=”crossoorigin=“匿名”></script><脚本src=“https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.20/lodash.min.js" 完整性=“sha512-90vH1Z83AJY9DmlWa8WkjkV79yfS2n2Oxhsi2dZbIv0nC4E6m5AbH8Nh156kkM7JePmqD6tcZsfad1ueoaovww==”crossoorigin=“匿名”></script>此shippet只显示性能测试中使用的函数,而不执行测试本身!
下面是铬的示例结果
好的,在回答问题之前,让我们先给你这个概念,在JavaScript中,函数是Object,也可以是null、Object、Array甚至Date,所以正如你所看到的,没有一种简单的方法像typeof obj==“Object”,所以上面提到的一切都会返回true,但是有一些方法可以通过编写函数或使用JavaScript框架来检查它,好的:
现在,假设您有一个真正的对象(不是null、函数或数组):
var obj = {obj1: 'obj1', obj2: 'obj2'};
纯JavaScript:
//that's how it gets checked in angular framework
function isObject(obj) {
return obj !== null && typeof obj === 'object';
}
or
//make sure the second object is capitalised
function isObject(obj) {
return Object.prototype.toString.call(obj) === '[object Object]';
}
or
function isObject(obj) {
return obj.constructor.toString().indexOf("Object") > -1;
}
or
function isObject(obj) {
return obj instanceof Object;
}
您可以简单地在代码中使用上述函数之一,方法是调用它们,如果它是一个对象,则返回true:
isObject(obj);
如果您使用的是JavaScript框架,他们通常会为您准备这些类型的函数,其中很少:
jQuery:
//It returns 'object' if real Object;
jQuery.type(obj);
角度:
angular.isObject(obj);
Undercore和Lodash:
//(NOTE: in Underscore and Lodash, functions, arrays return true as well but not null)
_.isObject(obj);
如果明确希望检查给定值是否为{}。
function isObject (value) {
return value && typeof value === 'object' && value.constructor === Object;
}
推荐文章
- 我如何检查如果一个变量是JavaScript字符串?
- 如何检测如果多个键被按下一次使用JavaScript?
- 如何通过history. pushstate获得历史变化的通知?
- IEEE 754浮点数不能精确表示的第一个整数是哪一个?
- 使用jQuery改变输入字段的类型
- 在JavaScript中,什么相当于Java的Thread.sleep() ?
- 使用jQuery以像素为整数填充或边距值
- c++中size_t和int的区别是什么?
- 检查是否选择了jQuery选项,如果没有选择默认值
- Next.js React应用中没有定义Window
- 如何重置笑话模拟函数调用计数之前,每次测试
- 如何强制一个功能React组件渲染?
- 在javascript中从平面数组构建树数组
- 将Dropzone.js与其他字段集成到现有的HTML表单中
- 如何在AngularJS中观察路由变化?