如何检查值是否是JavaScript中的对象?


当前回答

考虑-typeof bar==“object”以确定bar是否为对象

虽然typeof bar==“object”是检查bar是否为对象的可靠方法,但JavaScript中令人惊讶的是,null也被视为对象!

因此,令大多数开发人员惊讶的是,以下代码将在控制台中记录true(而不是false):

var bar=空;console.log(类型栏==“对象”);//日志为真!只要意识到这一点,也可以通过检查bar是否为空来轻松避免该问题:

console.log((bar!==null)&&(typeof bar==“object”));//日志错误为了彻底回答,还有两件事值得注意:

首先,如果bar是一个函数,上述解决方案将返回false。在大多数情况下,这是所需的行为,但在希望函数也返回true的情况下,可以将上述解决方案修改为:

console.log((bar!==null)&&((bar类型==“对象”)||(bar类型===“函数”));其次,如果bar是一个数组(例如,如果varbar=[];),上述解决方案将返回true。在大多数情况下,这是所需的行为,因为数组确实是对象,但在您希望数组也为false的情况下,可以将上述解决方案修改为:

console.log((bar!==null)&&(typeof bar==“object”)&&“[对象数组]”);然而,还有另一种方法可以为null、数组和函数返回false,但为对象返回true:

console.log((bar!==null)&&(bar.constructor==Object));或者,如果您正在使用jQuery:

console.log((bar!==null)&&(typeof bar==“object”)&&;

ES5使数组情况非常简单,包括它自己的空检查:

console.log(Array.isArray(bar));

其他回答

只需检查对象或数组,无需额外的函数调用(速度)。同样张贴在这里。

isArray()

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文本,因为它对自定义对象(如newDate或newYourCustomObject)返回false。

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

让我们在Javascript中定义“对象”。根据MDN文档,每个值都是对象或基元:

基元,基元值不是对象且没有任何方法的数据。JavaScript有7种原始数据类型:string、number、bigint、boolean、undefined、symbol和null。

什么是原始人?

3.“abc”真的无效的未定义

什么是对象(即不是基元)?

对象.原型Object.prototype派生的所有内容功能.原型对象作用函数C(){}--用户定义函数C.prototype——用户定义函数的原型属性:这不是Cs原型new C()--“new”-ing用户定义的函数数学阵列.原型阵列{“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===“对象”无法工作,因为误报(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,如果其参数不是对象,则抛出异常:

// 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({})

表演

今天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只显示性能测试中使用的函数,而不执行测试本身!

下面是铬的示例结果

可随时使用的检查功能

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(函数(){}));

这是一个老问题,但我想把它留在这里。大多数人都在检查变量是否为{},这意味着一个键值配对,而不是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返回的数据库调用。然后,我们可以测试是否不是数组、是否为null、是否为“function”类型、是否为Object

// 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