ajsie
ajsie

Reputation: 79716

Check that value is object literal?

I have a value and want to know if it's an iteratable object literal, before I iterate it.

How do I do that?

Upvotes: 33

Views: 20519

Answers (14)

Ryan Taylor
Ryan Taylor

Reputation: 13425

If you use obj instanceof Object or typeof obj === "object" you get false positives on things like new Number(3) and arrays ([1,2,3]).

Using o.constructor === Object is great, however there's a weird edge case of Object.create(null) – which does, in fact, give you a plain object, albeit not one created in a "normal" way. Conceptually it gives a valid, normal, undecorated object. We check for this case with Object.getPrototypeOf(o) === null which will only hold true for the above undecorated object type.

The Boolean(o) converts null or undefined to false. People were complaining about it above, and honestly o && ... is more succinct and unless you're serializing it doesn't matter. Nevertheless, I included it.

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

function isObject1(o) {
  return Boolean(o) && o.constructor === Object
}

function isObject2(o) {
  // edge case where you use Object.create(null) –– which gives an object {} with no prototype
  return Boolean(o) && (Object.getPrototypeOf(o) === null || o.constructor === Object)
}

Upvotes: 3

Maxim Secret
Maxim Secret

Reputation: 31

Obj && typeof Obj === 'object' && !Array.isArray(Obj); 

Upvotes: 0

user17386646
user17386646

Reputation:

adding to user user113716: (public utility)

function typeOfObj(obj) {
    if(typeof obj === 'function' && String(obj).search('class') === 0) return 'class';
    return Object.prototype.toString.call(obj).replace(/.*\w*\s(\w*).*/,'$1').toLowerCase();
}

if(typeof obj !== 'undefined' && typeOfObj(obj) == 'object') true;

Upvotes: 0

Lucas Tettamanti
Lucas Tettamanti

Reputation: 1810

const isObject = (x) => {
  return Object.prototype.toString.call(x) == "[object Object]";
}

That works for me.

Upvotes: 0

bhdrk
bhdrk

Reputation: 3495

Vanilla Javascript version of JQuery.isPlainObject function.

var class2type = {};
var toString = class2type.toString;
var getProto = Object.getPrototypeOf;
var hasOwn = class2type.hasOwnProperty;
var fnToString = hasOwn.toString;
var ObjectFunctionString = fnToString.call(Object);

function isPlainObject(obj) {
  var proto, Ctor;

  // Detect obvious negatives
  // Use toString instead of jQuery.type to catch host objects
  if (!obj || toString.call(obj) !== "[object Object]") {
    return false;
  }

  proto = getProto(obj);

  // Objects with no prototype (e.g., `Object.create( null )`) are plain
  if (!proto) {
    return true;
  }

  // Objects with prototype are plain iff they were constructed by a global Object function
  Ctor = hasOwn.call(proto, "constructor") && proto.constructor;
  return typeof Ctor === "function" && fnToString.call(Ctor) === ObjectFunctionString;
}

Example:

isPlainObject({}) // true
isPlainObject( "test" ) // false

Upvotes: 0

Conrad Damon
Conrad Damon

Reputation: 711

Strangely, I'm seeing different values for toString() for a subclassed object depending how toString() is being called:

Object.prototype.toString.call(aThing)
"[object Object]"

aThing.toString()
"ZmPopupMenu"

That results in a false positive, so I amended it to prefer the object's toString():

var str = someObject.toString
    ? someObject.toString()
    : Object.prototype.toString.call(someObject);
return str === '[object Object]';

Upvotes: 0

Leonardo Ciaccio
Leonardo Ciaccio

Reputation: 3126

Little gist, not really elegant but efficient

function _isObj( _obj ){

   return ( typeof _obj === "object" && JSON.stringify( _obj ).indexOf( "{" ) == 0 ); 

}

Little example

function _isObj( _obj ){

   return ( typeof _obj === "object" && JSON.stringify( _obj ).indexOf( "{" ) == 0 ); 

}

var p = document.createElement( "p" );
p.textContent = "undefined : " + _isObj( undefined );
document.body.appendChild( p );

p = document.createElement( "p" );
p.textContent = "null : " + _isObj( null );
document.body.appendChild( p );

p = document.createElement( "p" );
p.textContent = "boolean : " + _isObj( true );
document.body.appendChild( p );

p = document.createElement( "p" );
p.textContent = "function : " + _isObj( function(){} );
document.body.appendChild( p );

p = document.createElement( "p" );
p.textContent = "array : " + _isObj( [] );
document.body.appendChild( p );

p = document.createElement( "p" );
p.textContent = "string : " + _isObj( "{}" );
document.body.appendChild( p );
document.body.appendChild( p );
document.body.appendChild( p );

p = document.createElement( "p" );
p.textContent = "number : " + _isObj( 1 );
document.body.appendChild( p );
document.body.appendChild( p );

p = document.createElement( "p" );
p.textContent = "object : " + _isObj( {} );
document.body.appendChild( p );

p = document.createElement( "p" );
p.textContent = "another object : " + _isObj( p );
document.body.appendChild( p );

hope this help

Upvotes: -1

Mark
Mark

Reputation: 3163

Say you have some testvar and want to see if it is an object, but not an array or null (these are both of type Object). You can do the following

testVar instanceof Object && !Array.isArray(testVar) && testVar !== null

Upvotes: 3

GullerYA
GullerYA

Reputation: 1776

Bumping old thread, but it's still shows up in searches and people are even referencing it as duplicate for a new similar ones - and still the top-most answers here are far from being correct (sorry people, no offends).

To check if variable is an object the following should be used:

if (typeof variable === 'object') {
    // do something
}

Arrays are also objects, so this would be true for an array too. Moreover - null is a valid object as well, therefore the above will return true on null too. Personally, when really need to check if an expected variable is 'workable' object I'm always using this boringly repeated formula:

if (variable && typeof variable === `object`) {
    // do something
}

Last but not least :) please please please, do yourself a favor and don't use any libraries for such a simple things. Javascript is a fastly evolving language having today much much more than yesterday, so fast that most of the libraries are not even fast enough to fetch up. Beside it, people who are working on the spec are doing a great job and mostly the native APIs are clean, correct, making perfect sense and coherent with the rest of the language.

Upvotes: -1

Ehsan
Ehsan

Reputation: 1285

Well, you don't need to check everything by yourself or write your own codes, when there are good libraries such as Lodash and Underscore.

In Lodash, you can easily check it by isPlainObject function, e.g.:

_.isPlainObject({'a': 12});

Check this page: https://lodash.com/docs#isPlainObject

Upvotes: 0

MaxArt
MaxArt

Reputation: 22627

I think a function like this should be native, just like Array.isArray:

Object.isObject = function(obj) {
    return obj && obj.constructor === this || false;
};

This one doesn't make function calls nor string comparisons, and doesn't reference global objects (like Object), so it should be quite fast. I don't think this will used in performance intensive tasks though, but whatever.

I'm not totally convinced about the name... maybe something like Object.isLiteral would be better.

It can cause problem with host objects, though, but I don't have a test ready.

Upvotes: 2

NeonMonk
NeonMonk

Reputation: 47

This works for me:

function isObject(o) {
    try {
        return ((typeof o == "object") && (o !== null) && (o.length === undefined));
    } catch (err) {
        return false;
    }
}

Upvotes: -2

dcestari
dcestari

Reputation: 440

You could also do something like:

    if (someObject.constructor == Object) {
        // do your thing
    }

you can read more about it here

Upvotes: 8

user113716
user113716

Reputation: 322502

This should do it for you:

if( Object.prototype.toString.call( someObject ) === '[object Object]' ) {
    // do your iteration
}

From ECMAScript 5 Section 8.6.2 if you're interested:

The value of the [[Class]] internal property is defined by this specification for every kind of built-in object. The value of the [[Class]] internal property of a host object may be any String value except one of "Arguments", "Array", "Boolean", "Date", "Error", "Function", "JSON", "Math", "Number", "Object", "RegExp", and "String". The value of a [[Class]] internal property is used internally to distinguish different kinds of objects. Note that this specification does not provide any means for a program to access that value except through Object.prototype.toString (see 15.2.4.2).

Upvotes: 44

Related Questions