tags:

views:

218

answers:

4

Assuming I declare

var ad = {}; 

How can I check whether this object will contain any user-defined properties?

+2  A: 
for(var memberName in ad)
{
  //Member Name: memberName
  //Member Value: ad[memberName]
}

Member means Member property, member variable, whatever you want to call it >_>

The above code will return EVERYTHING, including toString... If you only want to see if the object's prototype has been extended:

var dummyObj = {};  
for(var memberName in ad)
{
  if(typeof(dummyObj[memberName]) == typeof(ad[memberName])) continue; //note A
  //Member Name: memberName
  //Member Value: ad[memberName]

}

Note A: We check to see if the dummy object's member has the same type as our testing object's member. If it is an extend, dummyobject's member type should be "undefined"

ItzWarty
Hi, can I just know whether an object contain properties or not? Thanks
Ricky
in your solution there is no filtering for unwanted prototype properties, that means it might be misbehaving when using a library like Prototype.js or an unexperienced user added additional prototype properties to the object.
Joscha
check out Daniels solution on this page - its less error-prone!
Joscha
Your first code block does not cover it at all. the second code block misbehaves if I add a variable to the "ad" object which is undefined. Really, check out Daniels answer, it's the only correct one and fast, as it uses a native implementation called "hasOwnProperty".
Joscha
@Ricky: If you want to check whether an object contains properties, you can simply use the example in my answer: http://stackoverflow.com/questions/2673121/javascript-how-to-check-an-object-without-any-properties/2673141#2673141. If the code reaches the comment, your object would not have any direct properties. If not, it would.
Daniel Vassallo
If someone extended the `Object.prototype` with something, e.g. `Object.prototype.foo = "foo";`, the property will be resolvable in both objects, `dummyObj['foo'] === ad['foo'];` the `typeof` check doesn't helps much
CMS
+2  A: 

You can loop over the properties of your object as follows:

for(var prop in ad) {
    if (ad.hasOwnProperty(prop)) {
        // handle prop as required
    }
}

It is important to use the hasOwnProperty() method, to determine whether the object has the specified property as a direct property, and not inherited from the object's prototype chain.

Daniel Vassallo
Hi Daniel, actually I'm seeking a device to check whether an object contains user-defined properies or not. Not to check whether a specific property exist.
Ricky
@Ricky: You can put that code in a function, and make it return false as soon as it reaches the part where there is the comment.
Daniel Vassallo
A: 
for (var hasProperties in ad) break;
if (hasProperties)
    ... // ad has properties

If you have to be safe and check for Object prototypes (these are added by certain libraries and not there by default):

var hasProperties = false;
for (var x in ad) {
    if (ad.hasOwnProperty(x)) {
        hasProperties = true;
        break;
    }
}
if (hasProperties)
    ... // ad has properties
Casey Hope
in your solution there is no filtering for unwanted prototype properties, that means it might be misbehaving when using a library like Prototype.js or an unexperienced user added additional prototype properties to the object. Check out Daniels solution on this page.
Joscha
You don't have to use a library or be unexperienced to extend an object's prototype. _Some_ experienced programmers do this all the time.
Alsciende
+4  A: 

What about making a simple function?

function isEmptyObject(obj) {
  for(var prop in obj) {
    if (Object.prototype.hasOwnProperty.call(obj, prop)) {
      return false;
    }
  }
  return true;
}

isEmptyObject({}); // true
isEmptyObject({foo:'bar'});  // false

The hasOwnProperty method call directly on the Object.prototype is only to add little more safety, imagine the following using a normal obj.hasOwnProperty(...) call:

isEmptyObject({hasOwnProperty:'boom'});  // false

Note: (for the future) The above method relies on the for...in statement, and this statement iterates only over enumerable properties, in the currently most widely implemented ECMAScript Standard (3rd edition) the programmer doesn't have any way to create non-enumerable properties.

However this has changed now with ECMAScript 5th Edition, and we are able to create non-enumerable, non-writable or non-deletable properties, so the above method can fail, e.g.:

var obj = {};
Object.defineProperty(obj, 'test', { value: 'testVal', 
  enumerable: false,
  writable: true,
  configurable: true
});
isEmptyObject(obj); // true, wrong!!
obj.hasOwnProperty('test'); // true, the property exist!!

An ECMAScript 5 solution to this problem would be:

function isEmptyObject(obj) {
  return Object.getOwnPropertyNames(obj).length === 0;
}

The Object.getOwnPropertyNames method returns an Array containing the names of all the own properties of an object, enumerable or not, this method is being implemented now by browser vendors, it's already on the Chrome 5 Beta and the latest WebKit Nightly Builds.

Object.defineProperty is also available on those browsers and latest Firefox 3.7 Alpha releases.

CMS
What is the advantage to Object.prototype.hasOwnProperty.call(obj, prop) over obj.hasOwnProperty(prop)?
Casey Hope
@Casey, edited, if an object overrides the `hasOwnProperty` property, the function might crash... I know I'm a little bit paranoid... but sometimes you don't know in which kind of environment your code will be used, but you know what method you want to use...
CMS
+1 for answering this question... and other questions of the future! :)
Daniel Vassallo
Thanks @Daniel!
CMS
Note there is also a bug in IE where if you have a property with a name that matches a non-enumerable property in `Object.prototype`, it doesn't get enumerated by `for...in`. So `isEmptyObject({toString:1})` will fail. This is one of the unfortunate reasons you can't *quite* use `Object` as a general-purpose mapping.
bobince
@bobnice, Oh yes, that [bug](https://developer.mozilla.org/en/ECMAScript_DontEnum_attribute#JScript_DontEnum_Bug) is pretty serious, fortunately this is one of the ES-deviations that disappeared on IE9.
CMS