如何检查值是否是JavaScript中的对象?
当前回答
哦,我的上帝!我认为这可能比以往任何时候都要短,让我们看看:
短代码和最终代码
函数isObject(obj){返回obj!=null&&obj.constructor.name==“对象”}console.log(isObject({}))//返回trueconsole.log(isObject([]))//返回falseconsole.log(isObject(null))//返回false
解释
退货类型
typeof JavaScript对象(包括null)返回“object”
console.log(类型为null,类型为[],类型为{})
检查其构造函数
检查其构造函数属性会返回带有其名称的函数。
console.log(({}).cconstructor)//返回名为“Object”的函数console.log(([]).cconstructor)//返回名为“Array”的函数console.log((null).cconstructor)//引发错误,因为null实际上没有属性
Function.name简介
Function.name返回函数的只读名称或闭包的“匿名”。
console.log(({}).cconstructor.name)//返回“Object”console.log(([]).cconstructor.name)//返回“Array”console.log((null).cconstructor.name)//引发错误,因为null实际上没有属性
注意:截至2018年,Function.name可能无法在IE中工作https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/name#Browser_compatibility
其他回答
在阅读并尝试了许多实现之后,我注意到很少有人尝试检查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'}))))
由于对于如何正确处理这个问题似乎有很多困惑,我将留下我的2美分(这个答案符合规范,在任何情况下都会产生正确的结果):
测试原语:未定义的空布尔字符串数
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];
}
}());
测试对象排除:日期RegExp布尔数字字符串函数任意数组
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];
}
}());
表演
今天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只显示性能测试中使用的函数,而不执行测试本身!
下面是铬的示例结果
有点晚了。。。对于“普通对象”(我的意思是,像{'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”。:)
如果您已经在使用AngularJS,那么它有一个内置的方法,可以检查它是否是一个对象(不接受null)。
angular.isObject(...)
推荐文章
- 我如何使用Jest模拟JavaScript的“窗口”对象?
- 我如何等待一个承诺完成之前返回一个函数的变量?
- 在JavaScript中根据键值查找和删除数组中的对象
- 使嵌套JavaScript对象平放/不平放的最快方法
- 如何以及为什么'a'['toUpperCase']()在JavaScript工作?
- 有Grunt生成index.html不同的设置
- 文档之间的区别。addEventListener和window。addEventListener?
- 如何检查动态附加的事件监听器是否存在?
- 如何写setTimeout与参数Coffeescript
- 将JavaScript字符串中的多个空格替换为单个空格
- JavaScript: override alert()
- 重置setTimeout
- 如何确保<select>表单字段被禁用时提交?
- jQuery有不聚焦的方法吗?
- 反应钩子-正确的方式清除超时和间隔