检查值是否是JavaScript中的对象

Dan*_*Fox 1194 javascript types object javascript-objects

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

Chu*_*uck 1409

如果typeof yourVariable === 'object',它是一个对象或null.如果要排除null,只需创建它typeof yourVariable === 'object' && yourVariable !== null.

  • 函数也是对象,应该包含在您的检查中. (18认同)
  • 因为数组也被认为是一个对象,所以被否决了,所以你还应该检查 `Array.isArray(yourVariable)`。 (14认同)
  • @Tresdin最好的方法是运行`Object.prototype.toString.call(yourVar)`,_yourVar_你需要检查什么.在数组的情况下,`Object.prototype.toString.call([1,2])`返回`[object Array]` (8认同)
  • @RightSaidFred似乎`typeof null =='object'`将不会在[ES6]中修复(http://wiki.ecmascript.org/doku.php?id=harmony:typeof_null).他们说:"这项提案遭到拒绝.它是在V8中实现的,但事实证明它打破了很多现有网站.本着One JavaScript的精神,这是不可行的 (7认同)
  • 在这种情况下,`yourVariable!== null`会更好吗? (4认同)
  • 普通对象始终被认为是真值,而“null”则被认为是假值。这意味着第二个版本也可以写成 `typeof yourVariable === 'object' && yourVariable` (3认同)
  • @Orion的简单答案是将数组视为对象。要获得更详细的答案,您必须阅读[`typeof`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/typeof),因为它具有一些特殊情况不一定完全有意义。如果您试图区分数组和不是数组的对象,那么您绝对不希望使用`typeof`。 (2认同)
  • 使用`yourVariable && typeof yourVariable ==='object`而不是显式检查`null`是不是更可靠?如果`yourVariable`是'undefined`怎么办? (2认同)
  • 上面的解决方案没有考虑 RegExp 或 Date 对象,如果您需要支持这些对象类型,您需要先执行检查。`if( val && type val !== 'object && Object.prototype.toString.call(val) !== '[object RegExp]' && Object.prototype.toString.call(val) !== '[object Date ]') {...}` (2认同)
  • @AlexanderFlenniken 没有必要,因为 `typeof []` 返回 `"object"`,默认情况下数组将包含在检查中。 (2认同)

Mat*_*ick 516

让我们在Javascript中定义"对象".根据MDN文档,每个值都是对象或原语:

原始的,原始的价值

不是对象且没有任何方法的数据.JavaScript有5种原始数据类型:string,number,boolean,null,undefined.

什么是原始的?

  • 3
  • 'abc'
  • true
  • null
  • undefined

什么是对象(即不是原始对象)?

  • Object.prototype
  • 一切都来自于 Object.prototype
    • Function.prototype
      • Object
      • Function
      • function C(){} - 用户定义的功能
    • C.prototype- 用户定义函数的prototype属性:这不是 C原型
      • new C() - "新" - 用户定义的功能
    • Math
    • Array.prototype
      • 阵列
    • {"a": 1, "b": 2} - 使用文字符号创建的对象
    • new Number(3) - 基元周围的包装
    • ...... 许多其他事情 ......
  • Object.create(null)
  • 一切都来自于 Object.create(null)

如何检查值是否为对象

instanceof 本身不起作用,因为它错过了两个案例:

// oops:  isObject(Object.prototype) -> false
// oops:  isObject(Object.create(null)) -> false
function isObject(val) {
    return val instanceof Object; 
}
Run Code Online (Sandbox Code Playgroud)

typeof x === 'object'因为误报(null)和漏报(函数)而无效:

// oops: isObject(Object) -> false
function isObject(val) {
    return (typeof val === 'object');
}
Run Code Online (Sandbox Code Playgroud)

Object.prototype.toString.call 由于所有基元的误报,它将无法工作:

> Object.prototype.toString.call(3)
"[object Number]"

> Object.prototype.toString.call(new Number(3))
"[object Number]"
Run Code Online (Sandbox Code Playgroud)

所以我使用:

function isObject(val) {
    if (val === null) { return false;}
    return ( (typeof val === 'function') || (typeof val === 'object') );
}
Run Code Online (Sandbox Code Playgroud)

@ Daan的答案似乎也有效:

function isObject(obj) {
  return obj === Object(obj);
}
Run Code Online (Sandbox Code Playgroud)

因为,根据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({})
Run Code Online (Sandbox Code Playgroud)

  • `obj === Object(obj)`为数组返回`true`. (19认同)
  • @Illuminator数组*是Javascript中的*对象,正如我在回答中提到的那样. (6认同)
  • 为什么不 `({}).toString.apply(obj) === '[object Object]'` 这样区分数组和非数组的对象 (6认同)
  • `var x = []; console.log(x === Object(x)); //返回true` (5认同)

Mic*_*ker 468

尝试使用null和/或object.

编辑:这个答案给出了如何检查变量属性的想法,但它不是一个防弹配方(毕竟根本没有配方!)用于检查它是否是一个对象,远离它.由于人们倾向于在没有进行任何研究的情况下从这里寻找要复制的东西,我强烈建议他们转向另一个,最受欢迎(并且正确!)的答案.

  • `typeof`是一个运算符,所以不需要`()`. (197认同)
  • @ MichaelKrelin-hacker:这很不幸,因为它[混淆了人们](http://stackoverflow.com/questions/2797517/typeof-is-an-operator-and-a-function). (144认同)
  • 这个答案是不正确的.`typeof`为null返回'object',它不是一个对象,`instanceof`不适用于使用`Object.create(null)`创建的对象. (114认同)
  • 是的,没有必要.我只是喜欢这种方式. (64认同)
  • @RightSaidFred,我没有解释,但我绝对不想在这些表达式中添加额外的括号:) (11认同)
  • @Jonathan,有更好的理由拒绝我的回答,你有机会有军事背景吗?:) (8认同)
  • 这不应该是公认的答案.除了Jonathan提出的风格问题之外,它完全不正确,并没有提出例如@ matt-fenwick的答案中非常重要的细微之处. (8认同)
  • 数组也将作为"对象"返回,如:`someArray instanceof Object // true`或`typeof someArray ==='object'// true`.怎么样:`Object.prototype.toString.call(someObject)==="[object Object]"`或``[object Array]"`如果你试图检测一个数组? (4认同)
  • `typeof null` ...`object`! (3认同)
  • 考虑这个语句,数组也是对象,所以如果你的代码看起来像typeof(test)而test是一个数组,那么结果将是"object" (2认同)
  • 这个答案很糟糕,因为它没有告诉您原始答案或编辑中的秘密null问题,因为答案没有告诉您如何甚至在原始答案或编辑中使用typeof(要与之进行比较吗? ),并且因为在编辑过程中您编写了太多无用的文字,并没有改善答案。投票吧。 (2认同)
  • 投票不足,因为您至少应该提到`typeof null ==“ object”`。 (2认同)
  • 永远不要具体是*获胜者模式*:**尝试使用** `blabla` **和/或** `blabla` **某些东西。编辑:这个答案给出了一个想法** blabla ... (2认同)

Daa*_*aan 265

官方的underscore.js使用此检查来确定某些东西是否真的是一个对象

// Is a given variable an object?
_.isObject = function(obj) {
  return obj === Object(obj);
};
Run Code Online (Sandbox Code Playgroud)

UPDATE

underscore.js更新库现在是用下面的,因为在V8之前的错误和少量微速度优化.

// Is a given variable an object?
_.isObject = function(obj) {
  var type = typeof obj;
  return type === 'function' || type === 'object' && !!obj;
};
Run Code Online (Sandbox Code Playgroud)

  • 因为大多数时候你想区分{}和[]例如作为函数的输入 (57认同)
  • 在javascript中,数组也是一个对象,因此大多数时候你想要排除数组:`return obj === Object(obj)&& Object.prototype.toString.call(obj)!=='[object Array] "` (53认同)
  • 为什么要排除数组?它们是完整的物体. (20认同)
  • 很好的答案.处理`null`也是.应该是接受的答案. (6认同)
  • @Nickolai ..用于迭代嵌套对象. (5认同)
  • @Daan这就是为什么我们有_.isPlainObject()的原因。 (2认同)
  • [我的答案](http://stackoverflow.com/a/39187058/1529630)比较完整,但这是唯一一个对所有可能的值均正常工作的方法。希望赏金标志能使这个答案脱颖而出并达到顶峰。 (2认同)
  • 没有什么事情是万能的。有些对象是可迭代的,即使它们是对象,也应该作为数组处理,具体取决于应用程序。 (2认同)

Chr*_*phe 173

Object.prototype.toString.call(myVar) 将返回:

  • "[object Object]" 如果myVar是一个对象
  • "[object Array]" 如果myVar是一个数组
  • 等等

有关这方面的更多信息以及为什么它是typeof的一个很好的替代方案,请查看本文.

  • 我最近了解到`typeof [] ==='object'` - >`true`.这就是你需要这种方法. (11认同)
  • @MattFenwick我不认为这是OP试图识别的那种"对象" (3认同)
  • @Christophe为什么这么认为?恕我直言,在OP没有给出"对象"给出的任何其他定义的情况下,对我来说,最合适的是整个ECS规范中使用的那个. (3认同)
  • @Christophe不区分原语和**对象**.`Object.prototype.toString.call(3)` - >``[object Number]"`.`Object.prototype.toString.call(new Number(3))` - >``[object Number]`" (2认同)

zup*_*upa 100

仅用于检查对象或数组而无需额外的函数调用(速度).也发布在这里.

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
Run Code Online (Sandbox Code Playgroud)

isObject() - 注意:仅用于Object文字,因为它为自定义对象返回false,例如new Date或new YourCustomObject.

isObject = function(a) {
    return (!!a) && (a.constructor === Object);
};
console.log(isObject(        )); // false
console.log(isObject(    null)); // false
console.log(isObject(    true)); // false
console.log(isObject(       1)); // false
console.log(isObject(   'str')); // false
console.log(isObject(      [])); // false
console.log(isObject(new Date)); // false
console.log(isObject(      {})); // true
Run Code Online (Sandbox Code Playgroud)

  • 令人惊讶的是,最好的答案是到目前为止.这基本上回答了问题 - 这将在JSON中表示为以`{`字符开头的东西.对于数组的情况,只要您不需要支持IE <9,就可以使用`Array.isArray()`来确定某些内容是否为数组.它通过了您提供的所有测试用例. (7认同)
  • @zupa:什么!!一个? (3认同)
  • @ 3000好吧,如果我们遗漏了(!! a)部分它会崩溃,因为null和undefined没有构造函数.(!! a)过滤掉它们.这是否回答你的问题? (3认同)
  • @BradKent 如果没有双重否定 `!!a` `isObject(null)` 将返回 `null` 而不是 `false` (3认同)
  • @zupa @3000 `Boolean(a)` 更长,但更直观。只是不要使用`new Boolean(a)`:([这里是为什么](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean#Description))! (2认同)

Vla*_*pak 75

有功能Array.isArray:

function isObject(o) {
  return o !== null && typeof o === 'object' && Array.isArray(o) === false;
}
Run Code Online (Sandbox Code Playgroud)

没有功能Array.isArray:

只是惊讶了多少赞成错误答案
只有1个答案通过我的测试!在这里,我创建了我的简化版本:

function isObject(o) {
  return o instanceof Object && o.constructor === Object;
}
Run Code Online (Sandbox Code Playgroud)

至于我,它清晰简单,只是有效!在这里我的测试:

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
Run Code Online (Sandbox Code Playgroud)

还有一次:并非所有答案都通过了这个测试!


如果您需要验证该对象是否是特定类的实例,则必须使用您的特定类检查构造函数,例如:

function isDate(o) {
  return o instanceof Object && o.constructor === Date;
}
Run Code Online (Sandbox Code Playgroud)

简单测试:

var d = new Date();
console.log(isObject(d)); // Will return: false
console.log(isDate(d));   // Will return: true
Run Code Online (Sandbox Code Playgroud)

因此,您将拥有严格而强大的代码!


如果你不会喜欢创造功能isDate,isError,isRegExp,等你可以考虑选择使用这种广义函数:

function isObject(o) {
  return o instanceof Object && typeof o.constructor === 'function';
}
Run Code Online (Sandbox Code Playgroud)

对于前面提到的所有测试用例,它都无法正常工作,但它对所有对象(普通或构造)都足够好.


isObject如果Object.create(null)因为内部实现在这里Object.create解释,但你可以使用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;
};
Run Code Online (Sandbox Code Playgroud)

根据此实现,已经在npm v1上创建了!它适用于所有早期描述的测试用例!


jth*_*ter 74

我很喜欢:

function isObject (item) {
  return (typeof item === "object" && !Array.isArray(item) && item !== null);
}
Run Code Online (Sandbox Code Playgroud)

如果该项是JS对象,并且它不是JS数组,并且它不是null......如果所有三个都证明是真的,则返回true.如果三个条件中的任何一个失败,&&测试将短路false并将返回.在null如果需要的话(这取决于你如何使用测试可以省略null).

DOCS:

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

  • @macher因为`new Date()`返回一个对象.从逻辑的角度来看,数组不是对象 - 尽管JavaScript处理并报告它们.然而,在实践中,看到它们是平等的没有帮助,因为它们不是.例如,对象没有`length`属性,它没有像push()这样的方法.有时候你可能想要给一个函数重载params,你需要在数组或对象之间做出改变,特别是如果其他参数取决于给出的那个. (4认同)
  • @Oriol我既没有写过数组不是对象,也没有写过对象不能有`length`属性(我的意思是对象文字默认没有`length`属性).我写道,从*逻辑*的角度来看,数组不是对象.我说的是程序逻辑.有时需要检查数组是否是"真实"数组,而绝对不是"真实"对象.这就是`Array.isArray()`的用途.想象一下,你有一个接受一个对象或一个对象数组的函数.检查特殊属性或方法是一种肮脏的解决方案.本土方式总是更好. (4认同)
  • 那么console.log(isObject(new Date()))呢?为什么日期应该是对象而不是数组? (2认同)
  • @StanE 数组绝对是对象。不知道为什么你认为对象不能有“length”属性,也不能有“push”等方法,“Object.create(Array.prototype)”是具有这些属性的非数组对象的一个​​简单的反例。数组的特殊之处在于它们是具有自定义 [[DefineOwnProperty]] 基本内部方法的奇异对象,但它们仍然是对象。 (2认同)
  • typeof null是“对象”,而不是“未定义”。 (2认同)

Eri*_*eni 30

退货类型

typeof JavaScript构造函数和对象(包括null)返回"object"

function isObject(obj)
{
    return obj != null && obj.constructor.name === "Object"
}

console.log(isObject({})) // returns true
console.log(isObject([])) // returns false
console.log(isObject(null)) // returns false
Run Code Online (Sandbox Code Playgroud)

检查他们的构造函数

检查其constructor属性返回函数及其名称.

console.log(typeof null, typeof [], typeof {})
Run Code Online (Sandbox Code Playgroud)

介绍Function.name

Function.name返回函数的只读名称或"anonymous"闭包.

console.log(({}).constructor) // returns a function with name "Object"
console.log(([]).constructor) // returns a function with name "Array"
console.log((null).constructor) //throws an error because null does not actually have a property
Run Code Online (Sandbox Code Playgroud)

最终代码

console.log(({}).constructor.name) // returns "Object"
console.log(([]).constructor.name) // returns "Array"
console.log((null).constructor.name) //throws an error because null does not actually have a property
Run Code Online (Sandbox Code Playgroud)

注意: Function.name可能无法在IE中运行 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/name#Browser_compatibility

  • 我真的很喜欢这篇文章,简短而切中要点。据我所知,它只在一件事上失败了。if obj = `Object.create(null)` 以及为什么你要这样做......? (6认同)
  • 根据您的回答,我在 NodeJS 中的最终(ES11)助手是: `const isObject = (obj) =&gt; (obj ?? false)?.constructor?.name === "Object";` 谢谢! (3认同)

Ali*_*eza 29

OK,让我们给你这个概念首先回答你的问题,在JavaScript函数之前都是对象,也为null,对象,数组,甚至日期,所以你看有没有喜欢的typeof的obj ==="对象"一个简单的方法,所以上面提到的所有内容都将返回true,但有一些方法可以通过编写函数或使用JavaScript框架来检查它,OK:

现在,假设你有这个对象是一个真实的对象(不是null或函数或数组):

var obj = {obj1: 'obj1', obj2: 'obj2'};
Run Code Online (Sandbox Code Playgroud)

纯JavaScript:

//that's how it gets checked in angular framework
function isObject(obj) {
  return obj !== null && typeof obj === 'object';
}
Run Code Online (Sandbox Code Playgroud)

要么

//make sure the second object is capitalised 
function isObject(obj) {
   return Object.prototype.toString.call(obj) === '[object Object]';
}
Run Code Online (Sandbox Code Playgroud)

要么

function isObject(obj) {
    return obj.constructor.toString().indexOf("Object") > -1;
}
Run Code Online (Sandbox Code Playgroud)

要么

function isObject(obj) {
    return obj instanceof Object;
}
Run Code Online (Sandbox Code Playgroud)

您可以通过调用它们来简单地在代码中使用上述函数之一,如果它是一个对象,它将返回true:

isObject(obj);
Run Code Online (Sandbox Code Playgroud)

如果您使用的是JavaScript框架,他们通常会为您准备这些函数,这些函数很少:

jQuery的:

 //It returns 'object' if real Object;
 jQuery.type(obj);
Run Code Online (Sandbox Code Playgroud)

角度:

angular.isObject(obj);
Run Code Online (Sandbox Code Playgroud)

下划线和Lodash:

//(NOTE: in Underscore and Lodash, functions, arrays return true as well but not null)
_.isObject(obj);
Run Code Online (Sandbox Code Playgroud)


las*_*ild 23

这取决于你对"是一个对象"的意思.如果你想要一些不是原始的东西,即你可以设置新属性的东西,这应该可以解决问题:

function isAnyObject(value) {
    return value != null && (typeof value === 'object' || typeof value === 'function');
}
Run Code Online (Sandbox Code Playgroud)

它不包括原语(纯数字/ NaN/ Infinity,普通字符串,符号,true/ false,undefinednull),但应返回其他一切(包括真正的Number,BooleanString对象).请注意,JS没有定义"主机"对象(例如windowor console)应该在使用时返回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;
    }
}
Run Code Online (Sandbox Code Playgroud)

编辑2018:因为Symbol.toStringTag现在允许自定义输出Object.prototype.toString.call(...),所以在某些情况下,即使对象以文字形式开始生命,上述isPlainObject函数也可能返回false.可以说,按照惯例,具有自定义字符串标记的对象不再是一个普通对象,但这进一步混淆了普通对象在Javascript中的定义.


Ori*_*iol 17

检查值类型的最合理方法似乎是typeof运算符.唯一的问题是它可怕的破碎:

  • 它返回"object"null,属于null类型.
  • 它返回"function"属于Object类型的可调用对象.
  • 它可以返回(几乎)任何它想要的非标准非可调用对象.例如,IE似乎喜欢"unknown".唯一禁止的结果是"function"原始类型.

typeof对于非null原语只是可靠的.因此,检查值是否为对象的方法是确保返回的字符串typeof不对应于基元,而对象则不对应null.然而,问题是,未来的标准可能会引入新的基本类型,我们的代码会认为它是一个对象.新类型不会频繁出现,但例如ECMAScript 6引入了Symbol类型.

因此,typeof我只推荐其结果因值是否为对象而变化的方法,而不是.以下打算成为一个

测试值是否属于Object类型的正确方法的全面但非详尽的列表.

  • Object 构造函数

    Object构造胁迫传递的参数的对象.如果它已经是对象,则返回相同的对象.

    因此,您可以使用它来强制对象的值,并严格地将该对象与原始值进行比较.

    以下函数需要ECMAScript 3,它引入了===:

    function isObject(value) { /* Requires ECMAScript 3 or later */
      return Object(value) === value;
    }
    
    Run Code Online (Sandbox Code Playgroud)

    我喜欢这种方法,因为它简单且具有自我描述性,类似的检查也适用于布尔值,数字和字符串.但是,请注意它依赖于全局Object不被遮蔽或改变.

  • 构造函数

    实例化构造函数时,它可以返回与刚创建的实例不同的值.但除非它是一个对象,否则该值将被忽略.

    以下函数需要ECMAScript 3,它允许构造函数返回非对象.在ECMAScript 3之前发生了错误,但try当时的语句不存在.

    function isObject(value) { /* Requires ECMAScript 3 or later */
      return new function() { return value; }() === value;
    }
    
    Run Code Online (Sandbox Code Playgroud)

    虽然比前一个例子简单一点,但这个不依赖于任何全局属性,因此可能是最安全的.

  • this

    旧的ECMAScript规范要求该this值为对象.引入了ECMAScript 3 Function.prototype.call,它允许调用具有任意this值的函数,但强制转换为对象.

    ECMAScript 5引入了一种严格的模式来消除这种行为,但是在草率模式下我们仍然可以(但可以说不应该)依赖它.

    function isObject(value) { /* Requires ECMAScript 3 or later in sloppy mode */
      return function() { return this === value; }.call(value);
    }
    
    Run Code Online (Sandbox Code Playgroud)
  • [[原型]]

    所有普通对象都有一个名为[[Prototype]]的内部插槽,其值决定了它从哪个其他对象继承.该值只能是对象或null.因此,您可以尝试创建一个继承所需值的对象,并检查它是否有效.

    无论Object.createObject.getPrototypeOf需要的ECMAScript 5.

    function isObject(value) { /* Requires ECMAScript 5 or later */
      try {
        Object.create(value);
        return value !== null;
      } catch(err) {
        return false;
      }
    }
    
    Run Code Online (Sandbox Code Playgroud)
    function isObject(value) { /* Requires ECMAScript 5 or later */
      function Constructor() {}
      Constructor.prototype = value;
      return Object.getPrototypeOf(new Constructor()) === value;
    }
    
    Run Code Online (Sandbox Code Playgroud)
  • 一些新的ECMAScript 6方式

    ECMAScript 6引入了一些新的间接方法来检查一个值是一个对象.他们使用先前看到的方法将值传递给需要对象的一些代码,这些代码包含在try语句中以捕获错误.一些隐藏的例子,不值得评论

    function isObject(value) { /* Requires ECMAScript 6 or later */
      try {
        Object.setPrototypeOf({}, value);
        return value !== null;
      } catch(err) {
        return false;
      }
    }
    Run Code Online (Sandbox Code Playgroud)

    function isObject(value) { /* Requires ECMAScript 6 or later */
      try {
        new WeakSet([value]);
        return true;
      } catch(err) {
        return false;
      }
    }
    Run Code Online (Sandbox Code Playgroud)


注意:我故意跳过一些方法,如Object.getPrototypeOf(value)(ES5)和Reflect方法(ES6),因为它们调用了必要的内部方法,这可能会产生令人讨厌的事情,例如,如果value是代理.出于安全原因,我的示例仅参考value而不直接访问它.

  • "只有我的回答和Daan的完全正确." 鉴于我完全不同意你的前两句话,这有点冒昧. (2认同)
  • @zzzzBov 该问题询问如何检查某物是否为对象。ECMAScript 定义了对象是什么,所以我使用该定义。我看不到任何其他合理的解释。在某些情况下,执行其他操作(例如排除数组)的答案可能很有用,但它们不会检查某物是否为对象。 (2认同)

kus*_*lvm 17

天哪,其他答案太混乱了.

简答

typeof anyVar == 'object' && anyVar instanceof Object && !(anyVar instanceof Array)

要测试它,只需在chrome控制台中运行以下语句.

情况1.

var anyVar = {};
typeof anyVar == 'object' && anyVar instanceof Object && !(anyVar instanceof Array) // true
Run Code Online (Sandbox Code Playgroud)

案例2.

anyVar = [];
typeof anyVar == 'object' && anyVar instanceof Object && !(anyVar instanceof Array) // false
Run Code Online (Sandbox Code Playgroud)

案例3.

anyVar = null;
typeof anyVar == 'object' && anyVar instanceof Object && !(anyVar instanceof Array); // false
Run Code Online (Sandbox Code Playgroud)

说明

好吧.让我们分手吧

typeof anyVar == 'object'从三位候选人那里得到回报 - [], {} and null,

anyVar instanceof Object 将这些候选人缩小到两个 - [], {}

!(anyVar instanceof Array) 缩小到只有一个 - {}

请滚筒!

通过这个你可能已经学会了如何在Javascript中检查数组.

  • 值得注意的是,当anyVar是函数时,它也会返回false(根据需要)。 (2认同)

Tal*_*lha 16

试试这个

if (objectName instanceof Object == false) {
  alert('Not an object');
}
else {
  alert('An object');
}
Run Code Online (Sandbox Code Playgroud)

  • 为什么你要检查布尔值? (13认同)
  • 这错过了两种情况:`Object.prototype instanceof Object` - > false.`Object.create(null)instanceof Object` - > false. (4认同)
  • 这段代码假设数组作为对象。 (2认同)

Jay*_*wal 15

这是一个带有可选链接的答案,也许是isObj这个问题的最小函数。

const isObj = o => o?.constructor === Object;

// True for this
console.log(isObj({}));        // object!

// False for these
console.log(isObj(0));         // number
console.log(isObj([]));        // array
console.log(isObj('lol'));     // string
console.log(isObj(null));      // null
console.log(isObj(undefined)); // undefined
console.log(isObj(() => {}));  // function
console.log(isObj(Object));    // class
Run Code Online (Sandbox Code Playgroud)

  • @TinyRoy 不是应该这样吗?错误实例不是对象。如果我有什么问题请告诉我。:) (2认同)

Kan*_*nia 12

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
Run Code Online (Sandbox Code Playgroud)

我被要求提供更多细节.检查我们的变量是否是对象的最干净和可理解的方法是typeof myVar.它返回一个字符串类型(例如"object","undefined").

不幸的是,Array和null也有一个类型object.要仅使用真实对象,需要使用instanceof运算符检查继承链.它将消除null,但Array在继承链中具有Object.

所以解决方案是:

if (myVar instanceof Object && !(myVar instanceof Array)) {
  // code for objects
}
Run Code Online (Sandbox Code Playgroud)


Ina*_*mus 12

准备使用功能进行检查

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
Run Code Online (Sandbox Code Playgroud)

说明

  • 在Javascript中,null,Object,Array,Datefunctions为所有对象.虽然,null有点做作.因此,最好检查第null一个,检测它不是空的.

  • 检查作为对象的typeof o === 'object'保证o.如果没有这个检查,那Object.prototype.toString将毫无意义,因为它会返回对象,即使是undefinednull!例如:toString(undefined)退货[object Undefined]!

    typeof o === 'object'检查,toString.call(O)是检查是否一个伟大的方法o是一个对象,一个派生对象像Array,Date或一个function.

  • isDerivedObject功能中,它检查o是一个功能.因为,功能也是一个对象,这就是为什么它在那里.如果没有这样做,函数将返回false.示例: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));
}

// TESTS

// is null an object?

console.log(
  'is null an object?', isObject(null)
);

console.log(
  'is null a derived object?', isDerivedObject(null)
);

// is 1234 an object?

console.log(
  'is 1234 an object?', isObject(1234)
);

console.log(
  'is 1234 a derived object?', isDerivedObject(1234)
);

// is new Number(1234) an object?

console.log(
  'is new Number(1234) an object?', isObject(new Number(1234))
);

console.log(
  'is new Number(1234) a derived object?', isDerivedObject(1234)
);

// is function object an object?

console.log(
  'is (new (function (){})) an object?', 
  isObject((new (function (){})))
);

console.log(
  'is (new (function (){})) a derived object?', 
  isObject((new (function (){})))
);

// is {} an object?

console.log(
  'is {} an object?', isObject({})
);

console.log(
  'is {} a derived object?', isDerivedObject({})
);

// is Array an object?

console.log(
  'is Array an object?',
  isObject([])
)

console.log(
  'is Array a derived object?',
  isDerivedObject([])
)

// is Date an object?

console.log(
  'is Date an object?', isObject(new Date())
);

console.log(
  'is Date a derived object?', isDerivedObject(new Date())
);

// is function an object?

console.log(
  'is function an object?', isObject(function(){})
);

console.log(
  'is function a derived object?', isDerivedObject(function(){})
);
Run Code Online (Sandbox Code Playgroud)


Emi*_*lía 11

很晚才......对于"普通物体"(我的意思是,像{'x':5,'y':7})我有这个小片段:

function isPlainObject(o) {
   return ((o === null) || Array.isArray(o) || typeof o == 'function') ?
           false
          :(typeof o == 'object');
}
Run Code Online (Sandbox Code Playgroud)

它会生成下一个输出:

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
Run Code Online (Sandbox Code Playgroud)

它总是适合我.如果"o"的类型是"object"但是没有null,数组或函数,则返回"true".:)


Pat*_*Pat 9

lodash有isPlainObject,这可能是许多访问此页面的人正在寻找的东西.给出函数或数组时返回false.


c7x*_*43t 9

由于关于如何正确处理这个问题似乎有很多困惑,我将留下2美分(这个答案符合规范并在所有情况下产生正确的结果):

测试原语: undefined null boolean string number

function isPrimitive(o){return typeof o!=='object'||null}
Run Code Online (Sandbox Code Playgroud)

对象不是原始的:

function isObject(o){return !isPrimitive(o)}
Run Code Online (Sandbox Code Playgroud)

或者:

function isObject(o){return o instanceof Object}
function isPrimitive(o){return !isObject(o)}
Run Code Online (Sandbox Code Playgroud)

测试任何数组:

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];
    }
}());
Run Code Online (Sandbox Code Playgroud)

测试对象排除:Date RegExp Boolean Number String Function任何数组

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];
    }
}());
Run Code Online (Sandbox Code Playgroud)


小智 8

当其他一切都失败时,我用这个:

var isObject = function(item) {
   return item.constructor.name === "Object";
}; 
Run Code Online (Sandbox Code Playgroud)

  • 为什么要进行字符串比较,为什么不简单地使用“item.constructor === Object”? (2认同)

piz*_*r0b 8

这会奏效.它是一个返回true,false或null的函数.

const isObject = obj => obj && obj.constructor && obj.constructor === Object;

console.log(isObject({})); // true
console.log(isObject([])); // false
console.log(isObject(new Function)); // false
console.log(isObject(new Number(123))); // false
console.log(isObject(null)); // null
Run Code Online (Sandbox Code Playgroud)

  • @SeregPie将来你应该避免在答案中编辑代码.正如这个答案所代表的那样,在测试时,我确实获得了"null"作为最终测试的结果而不是"false".请参阅[我应该何时编辑代码?](https://meta.stackoverflow.com/questions/260245/when-should-i-make-edits-to-code) (2认同)

Chr*_*yan 8

为了我的代码的目的,我发现这个决定与上面的一些答案相对应:

ES6 变体:

const checkType = o => Object.prototype
                    .toString
                    .call(o)
                    .replace(/\[|object\s|\]/g, '')
                    .toLowerCase();
Run Code Online (Sandbox Code Playgroud)

ES5 变体:

function checkType(o){
   return Object.prototype
                    .toString
                    .call(o)
                    .replace(/\[|object\s|\]/g, '')
                    .toLowerCase();
}
Run Code Online (Sandbox Code Playgroud)

您可以非常简单地使用它:

checkType([]) === 'array'; // true
checkType({}) === 'object'; // true
checkType(1) === 'number'; // true
checkType('') === 'string'; // true
checkType({}.p) === 'undefined'; // true
checkType(null) === 'null'; // true
Run Code Online (Sandbox Code Playgroud)

等等..

  • 或者可以使用 `slice(8, -1)` 代替 `replace(/\[|object\s|\]/g, '')`。它运行得快得可怕。 (2认同)

Mah*_*ary 7

if(typeof value === 'object' && value.constructor === Object)
{
    console.log("This is an object");
}
Run Code Online (Sandbox Code Playgroud)


Dav*_*uer 7

所述Ramda功能库具有用于检测JavaScript类型中一个精彩功能.

解释全部功能:

function type(val) {
  return val === null      ? 'Null'      :
         val === undefined ? 'Undefined' :
         Object.prototype.toString.call(val).slice(8, -1);
}
Run Code Online (Sandbox Code Playgroud)

当我意识到解决方案的简单和美观时,我不得不笑.

Ramda 文档的示例用法:

R.type({}); //=> "Object"
R.type(1); //=> "Number"
R.type(false); //=> "Boolean"
R.type('s'); //=> "String"
R.type(null); //=> "Null"
R.type([]); //=> "Array"
R.type(/[A-z]/); //=> "RegExp"
R.type(() => {}); //=> "Function"
R.type(undefined); //=> "Undefined"
Run Code Online (Sandbox Code Playgroud)


sas*_*asi 7

如果您要检查prototypefor的object唯一来源Object。过滤掉StringNumberArrayArguments,等。

function isObject (n) {
  return Object.prototype.toString.call(n) === '[object Object]';
}
Run Code Online (Sandbox Code Playgroud)

或作为单表达式箭头功能(ES6 +)

const isObject = n => Object.prototype.toString.call(n) === '[object Object]'
Run Code Online (Sandbox Code Playgroud)


Gus*_*Wal 7

阅读和尝试了很多的实现之后,我发现很少有人尝试检查类似值JSONMathdocument再与原型链或物体比1步。

typeof我认为最好是将检查保持尽可能简单,以免在添加新的原始对象或本机对象注册为typeof“对象” 时进行重构,而不是检查变量的大小写然后消除边缘情况,这会更好。'。

毕竟,typeof操作员会告诉您某个对象是否是JavaScript的对象,但是JavaScript的对象定义对于大多数实际场景(例如typeof null === 'object')而言太宽泛了。下面是一个函数,该函数v通过本质上重复两次检查来确定变量是否为对象:

  1. 一个循环开始,只要区域的字符串版本继续v'[object Object]'
    我希望函数的结果与下面的日志完全一样,所以这是我最后得到的唯一“对象”条件。如果失败,该函数立即返回false。
  2. v被替换为链中的下一个原型v = Object.getPrototypeOf(v),但之后也直接进行评估。当新的值为vis时null,这意味着包括根原型(很可能是链中唯一的原型)在内的每个原型都已通过while循环中的检查,我们可以返回true。否则,将开始新的迭代。

function isObj (v) {
  while (     Object.prototype.toString.call(v) === '[object Object]')
  if    ((v = Object.getPrototypeOf(v))         === null)
  return true
  return false
}

console.log('FALSE:')
console.log('[]                   -> ', isObj([]))
console.log('null                 -> ', isObj(null))
console.log('document             -> ', isObj(document))
console.log('JSON                 -> ', isObj(JSON))
console.log('function             -> ', isObj(function () {}))
console.log('new Date()           -> ', isObj(new Date()))
console.log('RegExp               -> ', isObj(/./))

console.log('TRUE:')
console.log('{}                   -> ', isObj({}))
console.log('new Object()         -> ', isObj(new Object()))
console.log('new Object(null)     -> ', isObj(new Object(null)))
console.log('new Object({})       -> ', isObj(new Object({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 inheritance     -> ', isObj(Object.create(Object.create({foo: 'bar'}))))
Run Code Online (Sandbox Code Playgroud)


Gil*_*ert 7

这是一个老问题,但想把它留在这里。大多数人正在检查变量是否{}表示键值对,而不是 JavaScript 用于给定事物的下划线构造是什么,因为老实说,JavaScript 中的大部分内容都是对象。所以把它排除在外。如果你这样做...

let x = function() {}
typeof x === 'function' //true
x === Object(x) // true
x = []
x === Object(x) // true

// also
x = null
typeof null // 'object'
Run Code Online (Sandbox Code Playgroud)

大多数时候,我们想要知道我们是否有来自 API 的资源对象或从 ORM 返回的数据库调用。然后我们可以测试是否不是 an Array,不是null,不是 typeof '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
Run Code Online (Sandbox Code Playgroud)


Kam*_*ski 7

表现

今天 2020.09.26 我在 Chrome v85、Safari v13.1.2 和 Firefox v80 上对 MacOs HighSierra 10.13.6 进行测试,以选择解决方案。

结果

  • 在所有情况下,解决方案 C 和 H 在所有浏览器上都是最快/最快的
  • 在所有情况下,解决方案 D 和 G 在所有浏览器上都很慢/最慢

在此处输入图片说明

细节

我为解决方案执行了 3 个测试用例 A B C D E F G H I J K L M N O P Q R S T U V

  • 对于小对象 - 你可以在这里运行
  • 对于大对象 - 你可以在这里运行
  • 没有对象 - 你可以在这里运行它

下面的代码片段展示了解决方案之间的差异。Solutions AG 为Matt Fenwick描述的选定案例提供正确答案

// https://stackoverflow.com/a/14706877/860099
function A(x) {
  return x === Object(x);
};

// https://stackoverflow.com/a/42250981/860099
function 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
function E(x) { 
  return function() { return this === x; }.call(x);
}

// https://stackoverflow.com/a/39187058/860099
function F(x) { /* Requires ECMAScript 5 or later */
  try {
    Object.create(x);
    return x !== null;
  } catch(err) {
    return false;
  }
}

// https://stackoverflow.com/a/39187058/860099
function G(x) { /* Requires ECMAScript 5 or later */
  function Constructor() {}
  Constructor.prototype = x;
  return 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
function 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
function K(x)
{
    let t= JSON.stringify(x);
    return 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';
  let r;
  if (strict === true) {
    r = (instanceOfObject || typeOfObject) && (constructorUndefined || constructorObject);
  } else {
    r = (constructorUndefined || typeOfConstructorObject);
  }
  return r;
}

// https://stackoverflow.com/a/42250981/860099
function N(x) {
    return $.type(x) === 'object';
}

// https://stackoverflow.com/a/34864175/860099
function O(x) {
    if (Object.prototype.toString.call(x) !== '[object Object]') {
        return false;
    } else {
        var prototype = Object.getPrototypeOf(x);
        return prototype === null || prototype === 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 Function:
      case Boolean:
      case Symbol:
      case Date:
      case String:
      case RegExp:
        return x.constructor === Object;
      case Error:
      case EvalError:
      case RangeError:
      case ReferenceError:
      case SyntaxError:
      case TypeError:
      case URIError:
        return (Object === Error ? Error : x.constructor) === Object;
      case Array:
      case Int8Array:
      case Uint8Array:
      case Uint8ClampedArray:
      case Int16Array:
      case Uint16Array:
      case Int32Array:
      case Uint32Array:
      case Float32Array:
      case Float64Array:
        return (Object === Array ? Array : x.constructor) === Object;
      case Object:
      default:
        return (Object === Object ? Object : x.constructor) === Object;
    }
  } 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
function 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;
}




// -------------
// TEST
// -------------

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(`
Columns legend (test cases):
 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

Theoretically columns 1-6 should have have 1, columns 7-11 shoud have 0
`);
Run Code Online (Sandbox Code Playgroud)
<script
  src="https://code.jquery.com/jquery-3.5.1.min.js"
  integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0="
  crossorigin="anonymous"></script>
  
<script 
  src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.20/lodash.min.js" 
  integrity="sha512-90vH1Z83AJY9DmlWa8WkjkV79yfS2n2Oxhsi2dZbIv0nC4E6m5AbH8Nh156kkM7JePmqD6tcZsfad1ueoaovww==" 
  crossorigin="anonymous"></script>
  
This shippet only presents functions used in performance tests - it not perform tests itself!
Run Code Online (Sandbox Code Playgroud)

以下是 chrome 的示例结果

在此处输入图片说明


Ira*_*Ira 6

  var isObject = function(obj) {
    var type = typeof obj;
    return type === 'function' || type === 'object' && !!obj;
  };
Run Code Online (Sandbox Code Playgroud)

!!obj 是检查对象是否真实的简写(过滤掉null/undefined)


Car*_*los 6

如果明确要检查给定的值是否为{}.

function isObject (value) {
 return value && typeof value === 'object' && value.constructor === Object;
}
Run Code Online (Sandbox Code Playgroud)


ins*_*ign 6

function isObjectLike(value) {
  return value != null && typeof value == 'object' && !Array.isArray(value);
}
Run Code Online (Sandbox Code Playgroud)

基于lodash

  • 此解决方案将为数组返回 true,如下面指出的 @Exception。将 `&amp;&amp; !Array.isArray(value)` 添加到 return 语句将消除这种情况 (2认同)

am0*_*mhz 5

我从这个 SO 问题中找到了一种“新”方法来进行这种类型检查:为什么 instanceof 会为某些文字返回 false?

由此,我创建了一个用于类型检查的函数,如下所示:

function isVarTypeOf(_var, _type){
    try {
        return _var.constructor === _type;
    } catch(ex) {
        return false;         //fallback for null or undefined
    }
}
Run Code Online (Sandbox Code Playgroud)

那么你可以这样做:

console.log(isVarTypeOf('asdf', String));   // returns true
console.log(isVarTypeOf(new String('asdf'), String));   // returns true
console.log(isVarTypeOf(123, String));   // returns false
console.log(isVarTypeOf(123, Number));   // returns true
console.log(isVarTypeOf(new Date(), String));   // returns false
console.log(isVarTypeOf(new Date(), Number));   // returns false
console.log(isVarTypeOf(new Date(), Date));   // returns true
console.log(isVarTypeOf([], Object));   // returns false
console.log(isVarTypeOf([], Array));   // returns true
console.log(isVarTypeOf({}, Object));   // returns true
console.log(isVarTypeOf({}, Array));   // returns false
console.log(isVarTypeOf(null, Object));   // returns false
console.log(isVarTypeOf(undefined, Object));   // returns false
console.log(isVarTypeOf(false, Boolean));   // returns true
Run Code Online (Sandbox Code Playgroud)

已在 Chrome 56、Firefox 52、Microsoft Edge 38、Internet Explorer 11、Opera 43 上进行测试

编辑:
如果您还想检查变量是否为空或未定义,则可以改用它:

function isVarTypeOf(_var, _type){
    try {
        return _var.constructor === _type;
    } catch(ex) {
        return _var == _type;   //null and undefined are considered the same
        // or you can use === if you want to differentiate them
    }
}

var a = undefined, b = null;
console.log(isVarTypeOf(a, undefined)) // returns true
console.log(isVarTypeOf(b, undefined)) // returns true
console.log(isVarTypeOf(a, null)) // returns true
Run Code Online (Sandbox Code Playgroud)

从 inanc 的评论更新:接受挑战:D

如果你想松散比较对象,你可以尝试这种方式:

function isVarTypeOf(_var, _type, looseCompare){
    if (!looseCompare){
        try {
            return _var.constructor === _type;
        } catch(ex){
            return _var == _type;
        }
    } else {
        try{
            switch(_var.constructor){
                case Number:
                case Function:
                case Boolean:
                case Symbol:
                case Date:
                case String:
                case RegExp:
                    // add all standard objects you want to differentiate here
                    return _var.constructor === _type;
                case Error:
                case EvalError:
                case RangeError:
                case ReferenceError:
                case SyntaxError:
                case TypeError:
                case URIError:
                    // all errors are considered the same when compared to generic Error
                    return (_type === Error ? Error : _var.constructor) === _type;
                case Array:
                case Int8Array:
                case Uint8Array:
                case Uint8ClampedArray:
                case Int16Array:
                case Uint16Array:
                case Int32Array:
                case Uint32Array:
                case Float32Array:
                case Float64Array:
                    // all types of array are considered the same when compared to generic Array
                    return (_type === Array ? Array : _var.constructor) === _type;
                case Object:
                default:
                    // the remaining are considered as custom class/object, so treat it as object when compared to generic Object
                    return (_type === Object ? Object : _var.constructor) === _type;
            }
        } catch(ex){
            return _var == _type;   //null and undefined are considered the same
            // or you can use === if you want to differentiate them
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这样,你可以像 inanc 的评论一样:

isVarTypeOf(new (function Foo(){}), Object); // returns false
isVarTypeOf(new (function Foo(){}), Object, true); // returns true
Run Code Online (Sandbox Code Playgroud)

或者

Foo = function(){};
Bar = function(){};
isVarTypeOf(new Foo(), Object);   // returns false
isVarTypeOf(new Foo(), Object, true);   // returns true
isVarTypeOf(new Bar(), Foo, true);   // returns false
isVarTypeOf(new Bar(), Bar, true);   // returns true
isVarTypeOf(new Bar(), Bar);    // returns true
Run Code Online (Sandbox Code Playgroud)


归档时间:

查看次数:

1015451 次

最近记录:

5 年,9 月 前