检查值是否是JavaScript中的对象

如何检查值是否是JavaScript中的Object?


#1楼

尝试这个

if (objectName instanceof Object == false) {
  alert('Not an object');
}
else {
  alert('An object');
}

#2楼

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

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

有关此的更多信息以及为什么它是typeof的很好替代方法, 请查看本文


#3楼

官方underscore.js使用此检查来找出某物是否真的是一个对象

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

更新

由于V8中存在先前的错误以及较小的微速度优化,因此更新的underscore.js库现在正在使用以下内容。

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

#4楼

用于简单地检查对象或数组,而无需其他函数调用(速度)。 就像也在这里张贴。

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

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

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

#5楼

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

原始的原始值

不是对象且没有任何方法的数据。 JavaScript具有5种原始数据类型:字符串,数字,布尔值,空值,未定义。

什么是原始语?

  • 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; 
}

typeof x === 'object'不起作用,因为误报( 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({})

#6楼

我很喜欢:

function isObject (item) {
  return (typeof item === "object" && !Array.isArray(item) && item !== null);
}

如果项目是JS对象,并且不是JS数组,并且也不为null …如果所有三个都证明为true,则返回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


#7楼

当其他所有方法失败时,我将使用以下方法:

var isObject = function(item) {
   return item.constructor.name === "Object";
}; 

#8楼

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


#9楼

  var isObject = function(obj) {
    var type = typeof obj;
    return type === 'function' || type === 'object' && !!obj;
  };

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


#10楼

如果您已经在使用AngularJS,则它具有一个内置方法,该方法将检查其是否为对象(不接受null)。

angular.isObject(...)

#11楼

有点晚了...“普通对象”(我的意思是,像{'x':5,'y':7})我有这个小片段:

function isPlainObject(o) {
   return ((o === null) || Array.isArray(o) || typeof o == 'function') ?
           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”。 :)


#12楼

这取决于您对“是一个对象”的意思。 如果您希望所有不是原始类型的东西(即可以设置新属性的东西),都可以做到这一点:

function isAnyObject(value) {
    return value != null && (typeof value === 'object' || typeof value === 'function');
}

它排除了原语(普通数字/ NaN / Infinity ,纯字符串,符号, true / falseundefinednull ),但对于其他所有内容(包括NumberBooleanString对象)应返回true。 请注意,JS没有定义与typeof使用时应返回的“宿主”对象(例如windowconsole ,因此很难用这样的检查来覆盖。

如果您想知道某物是否是“普通”对象,即它是作为文字{}还是使用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.prototype.toString.call(...)的输出, Object.prototype.toString.call(...)即使对象开始以文字isPlainObject使用,上面的isPlainObject函数在某些情况下也可能返回false 。 可以说,按照惯例,带有自定义字符串标记的对象不再完全是普通对象,但这进一步混淆了Java中普通对象的定义。


#13楼

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

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

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

因此解决方案是:

if (myVar instanceof Object && !(myVar instanceof Array)) {
  // code for objects
}

#14楼

检查值类型的最合理方法似乎是typeof运算符。 唯一的问题是它被严重破坏了:

  • 它返回null "object" ,它属于Null类型。
  • 它为属于对象类型的可调用对象返回"function"
  • 它可以返回(几乎)非标准的不可调用对象所需的任何内容。 例如,IE似乎喜欢"unknown" 。 唯一禁止的结果是"function"和原始类型。

typeof仅对于非null原语是可靠的。 因此,检查值是否为对象的一种方法是确保typeof返回的字符串不对应于基本类型,并且该对象不为null 。 但是,问题在于将来的标准可能会引入新的原始类型,并且我们的代码会将其视为对象。 新类型并不经常出现,但是例如ECMAScript 6引入了Symbol类型。

因此,除了typeof ,我只推荐其结果根据值是否为对象而变化的方法。 以下打算成为

全面但不详尽的列表,列出了测试值是否属于对象类型的正确方法。

  • Object构造函数

    Object构造函数将传递的参数强制为一个对象。 如果已经是一个对象,则返回相同的对象。

    因此,您可以使用它来将值强制转换为对象,并将该对象与原始值进行严格比较。

    以下功能需要ECMAScript 3,它引入了===

     function isObject(value) { /* Requires ECMAScript 3 or later */ return Object(value) === value; } 

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

  • 建设者

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

    以下函数需要ECMAScript 3,它允许构造函数返回非对象。 在ECMAScript 3之前抛出了一个错误,但是那时不存在try语句。

     function isObject(value) { /* Requires ECMAScript 3 or later */ return new function() { return value; }() === value; } 

    虽然比上一个示例简单一些,但是此示例不依赖任何全局属性,因此可能是最安全的。

  • this

    旧的ECMAScript规范要求this值作为对象。 ECMAScript 3引入了Function.prototype.call ,该Function.prototype.call允许使用任意this值调用函数,但强制将其强制为对象。

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

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

    所有普通对象都有一个名为[[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; } } 
     function isObject(value) { /* Requires ECMAScript 5 or later */ function Constructor() {} Constructor.prototype = value; return Object.getPrototypeOf(new Constructor()) === value; } 
  • 一些新的ECMAScript 6种方式

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

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

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


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


#15楼

准备使用的功能进行检查

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中, nullObjectArrayDatefunction都是对象。 虽然, null是人为的。 因此,最好先检查null ,以检测它是否不是null。

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

    typeof o === 'object'检查之后,toString.call(o)是检查o是否是对象,派生对象(例如ArrayDatefunction )的好方法。

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


#16楼

好的,让我们在回答问题之前首先给您一个概念,在JavaScript函数中,对象是Object,null,Object,Arrays甚至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';
}

要么

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

要么

function isObject(obj) {
    return obj.constructor.toString().indexOf("Object") > -1;
}

要么

function isObject(obj) {
    return obj instanceof Object;
}

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

isObject(obj);

如果您使用的是JavaScript框架,那么他们通常会为您准备好这些功能,其中很少几个:

jQuery的:

 //It returns 'object' if real Object;
 jQuery.type(obj);

角度:

angular.isObject(obj);

下划线和Lodash:

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

#17楼

这将起作用。 它是一个返回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 


#18楼

我从以下SO问题中找到了一种执行这种类型检查的“新”方法: 为什么instanceof对某些文字返回false?

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

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

那么您可以执行以下操作:

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

已在Chrome 56,Firefox 52,Microsoft Edge 38,Internet Explorer 11,Opera 43上测试过

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

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

从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
        }
    }
}

这样,您可以像inanc的注释一样进行操作:

isVarTypeOf(new (function Foo(){}), Object); // returns false
isVarTypeOf(new (function Foo(){}), Object, true); // returns true

要么

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

#19楼

我喜欢用的是这个

function isObject (obj) {
  return typeof(obj) == "object" 
        && !Array.isArray(obj) 
        && obj != null 
        && obj != ""
        && !(obj instanceof String)  }

我认为在大多数情况下,日期必须作为对象通过检查,因此我不过滤日期


#20楼

使用Array.isArray函数:

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

没有函数Array.isArray

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

function isObject(o) {
  return o instanceof Object && o.constructor === Object;
}

对于我来说,它很简单明了,而且可以正常工作! 这是我的测试:

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

一次以上:并非所有答案都通过此测试! 🙈


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

function isDate(o) {
  return o instanceof Object && o.constructor === Date;
}

简单测试:

var d = new Date();
console.log(isObject(d)); // Will return: false
console.log(isDate(d));   // Will return: true

结果,您将获得严格而强大的代码!


如果您不会创建isDateisErrorisRegExp等函数, isError可以考虑使用此通用函数的选项:

function isObject(o) {
  return o instanceof Object && typeof o.constructor === 'function';
}

它不能在前面提到的所有测试用例中正常工作,但是对于所有对象(纯对象或构造对象)都足够好。


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;
};

基于此实现,已经在npm v1上创建了软件包 ! 它适用于所有先前描述的测试用例! 🙂


#21楼

它取决于用例,如果我们不想让数组和函数成为对象,则可以使用underscore.js内置函数。

function xyz (obj) { 
   if (_.isObject(obj) && !_.isFunction(obj) && !.isArray(obj)) {
     // now its sure that obj is an object 
   } 
}

#22楼

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

#23楼

Ramda功能库具有用于检测JavaScript类型的出色功能。

解释完整功能

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

当我意识到解决方案多么简单和美观时,我不得不大笑。

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"

#24楼

如果您想检查objectprototype是否仅来自Object 。 过滤掉StringNumberArrayArguments等。

function isObject (n) {
  return Object.prototype.toString.call(n) === '[object Object]';
}

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

const isObject = n => Object.prototype.toString.call(n) === '[object Object]'

#25楼

您可以使用JSON.stringify来测试您的对象,如下所示:

 var test = {} if(JSON.stringify(test)[0] === '{') { console.log('this is a Object') } 


#26楼

考虑typeof bar === "object"确定bar是否为对象

尽管typeof bar === "object"是检查bar是否为对象的可靠方法,但是JavaScript中令人惊讶的陷阱是null也被视为对象!

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

var bar = null; console.log(typeof bar === "object"); // logs true! 只要知道这一点,也可以通过检查bar是否为null来轻松避免该问题:

console.log((bar !== null) && (typeof bar === "object")); // logs false console.log((bar !== null) && (typeof bar === "object")); // logs false要完全回答我们的问题,还有两点值得注意:

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

console.log((bar !== null) && ((typeof bar === "object") || (typeof bar === "function"))); 其次,如果bar是一个数组(例如,如果var bar = []; ),则上述解决方案将返回true。 在大多数情况下,这是理想的行为,因为数组确实是对象,但是在您还希望对数组也为假的情况下,可以将上述解决方案修改为:

console.log((bar !== null) && (typeof bar === "object") && (toString.call(bar) !== "[object Array]")); 但是,还有另一种选择,它为null,数组和函数返回false,但对于对象返回true:

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

console.log((bar !== null) && (typeof bar === "object") && (! $.isArray(bar)));

ES5使数组的大小写非常简单,包括它自己的null检查:

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


#27楼

哦,我的上帝! 我认为这可能比以往更短,让我们看看:

简短代码和最终代码

 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 

解释

返回类型

typeof JavaScript对象(包括null )返回"object"

 console.log(typeof null, typeof [], typeof {}) 

检查他们的构造函数

检查其constructor属性将返回具有其名称的函数。

 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 

引入Function.name

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

 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 

注意:从2018年开始,Function.name可能无法在IE https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Function/name#Browser_compatibility中运行


#28楼

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

简短答案

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

要测试这一点,只需在chrome控制台中运行以下语句。

情况1。

var anyVar = {};
typeof anyVar == 'object' && anyVar instanceof Object && !(anyVar instanceof Array) // true

情况2

anyVar = [];
typeof anyVar == 'object' && anyVar instanceof Object && !(anyVar instanceof Array) // false

情况3。

anyVar = null;
typeof anyVar == 'object' && anyVar instanceof Object && !(anyVar instanceof Array); // false

说明

好吧,让我们分解一下

typeof anyVar == 'object'从三个候选值[], {} and null返回true,

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

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

请打鼓!

到此为止,您可能已经学习了如何在Javascript中检查数组。


#29楼

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

测试原语: undefined null boolean string number

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];
    }
}());

测试对象,但不包括以下内容: Date RegExp Boolean Number String Function any Array

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];
    }
}());

#30楼

在阅读并尝试了许多实现之后,我注意到很少有人尝试检查诸如JSONMathdocument或原型链长于1步的对象之类的值。

而不是检查的typeof我们的变量,然后黑客远离边缘的情况下,我想那会更好,如果检查保持尽可能简单,以避免重构时,有增加了新的原语或本地对象寄存器作为typeof的'宾语'。

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

  1. 只要v的字符串化版本为'[object Object]' ,就会开始继续循环。
    我希望函数的结果与下面的日志完全一样,所以这是我最后得到的唯一“对象”条件。 如果失败,该函数立即返回false。
  2. vv = Object.getPrototypeOf(v)替换为链中的下一个原型,但之后也会直接求值。 当v的新值为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'})))) 


#31楼

更新

这个答案是不完整的,并且会产生误导性的结果 。 例如,在JavaScript中, null也被认为是object类型,更不用说其他几种极端情况了。 请遵循以下建议,然后转到其他“必须投票(并且正确!)答案”


原始答案

尝试使用var instanceof something typeof(var)和/或var instanceof something

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


#32楼

如果typeof yourVariable === 'object'typeof yourVariable === 'object'对象或null。 如果要排除null,请将其类型设置为typeof yourVariable === 'object' && yourVariable !== null

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值