如何检查值是否是JavaScript中的对象?
当前回答
表演
今天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只显示性能测试中使用的函数,而不执行测试本身!
下面是铬的示例结果
其他回答
出于代码的目的,我找到了与上面的一些答案相对应的决定:
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
等等
这取决于你所说的“是一个物体”。如果您想要所有非原语的内容,即可以设置新财产的内容,那么这应该可以做到:
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中的纯对象定义。
更新:
这个答案是不完整的,给出了误导性的结果。例如,null也被认为是JavaScript中的对象类型,更不用说其他几种边缘情况。遵循下面的建议,然后转到其他“最支持(和正确!)的答案”:
typeof yourVariable === 'object' && yourVariable !== null
原答覆:
尝试使用typeof(var)和/或var instanceof。
编辑:这个答案给出了如何检查变量财产的思路,但它并不是检查它是否是一个对象的万无一失的方法(毕竟根本没有方法。
有点晚了。。。对于“普通对象”(我的意思是,像{'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有点做作。因此,最好先检查空值,以检测它是否为空。检查o==“object”的类型可确保o是一个对象。如果不进行此检查,Object.prototype.toString将毫无意义,因为它将返回任何对象,即使是未定义和null!例如:toString(undefined)返回[object undefined]!在typeofo=='object'检查之后,toString.call(o)是一个很好的方法来检查o是一个对象,还是一个派生对象,如Array、Date或函数。在isDerivedObject函数中,它检查o是否为函数。因为,函数也是一个对象,这就是它存在的原因。若并没有这样做,函数将返回false。示例:isDerivedObject(function(){})将返回false,但现在返回true。人们总是可以改变对象的定义。因此,可以相应地更改这些函数。
测验
函数isObject(o){返回null!=o&&typeof o==“对象”&&Object.pr原型.toString.call(o)==“[对象对象]”;}函数isDerivedObject(o){回来isObject(o)&&空!=o&&(类型o==“对象”| |类型o===“函数”)&&/^\[object/.test(object.protype.toString.call(o));}//测试//null是对象吗?控制台日志('是空的对象吗?',isObject(空));控制台日志('是否为null派生对象?',isDerivedObject(空));//1234是一个对象吗?控制台日志('1234是对象吗?',isObject(1234));控制台日志('1234是派生对象吗?',isDerivedObject(1234));//新编号(1234)是对象吗?控制台日志('新编号(1234)是对象吗?',isObject(新编号(1234)));控制台日志('新编号(1234)是派生对象吗?',isDerivedObject(1234));//函数对象是对象吗?控制台日志('是(new(function(){}))对象吗?',isObject((new(函数(){})));控制台日志(“(new(function(){}))是派生对象吗?”,isObject((new(函数(){})));//{}是对象吗?控制台日志(“是{}对象吗?”,isObject({}));控制台日志(“{}是派生对象吗?”,isDerivedObject({}));//Array是对象吗?控制台日志('数组是对象吗?',isObject([]))控制台日志('数组是派生对象吗?',isDerivedObject([]))//Date是对象吗?控制台日志('日期是对象吗?',isObject(新日期()));控制台日志('日期是派生对象吗?',isDerivedObject(新日期()));//函数是对象吗?控制台日志('函数是对象吗?',isObject(函数(){}));控制台日志('函数是派生对象吗?',isDerivedObject(函数(){}));
推荐文章
- 我如何使用Jest模拟JavaScript的“窗口”对象?
- 我如何等待一个承诺完成之前返回一个函数的变量?
- 在JavaScript中根据键值查找和删除数组中的对象
- 使嵌套JavaScript对象平放/不平放的最快方法
- 如何以及为什么'a'['toUpperCase']()在JavaScript工作?
- 有Grunt生成index.html不同的设置
- 文档之间的区别。addEventListener和window。addEventListener?
- 如何检查动态附加的事件监听器是否存在?
- 如何写setTimeout与参数Coffeescript
- 将JavaScript字符串中的多个空格替换为单个空格
- JavaScript: override alert()
- 重置setTimeout
- 如何确保<select>表单字段被禁用时提交?
- jQuery有不聚焦的方法吗?
- 反应钩子-正确的方式清除超时和间隔