6

I want to test whether an object is empty: {}. The following is typically used:

function isEmpty(obj) {
  for (var prop in obj) {
    if (obj.hasOwnProperty(prop))
      return false;
  }
  return true;
}

But suppose the Object prototype was added to as follows:

Object.prototype.Foo = "bar";

Tests:

alert(isEmpty({}));              // true
Object.prototype.Foo = "bar";
alert({}.Foo);                   // "bar" oh no...
alert(isEmpty({}));              // true  ...**huh?!**

I tried to nuke the object's prototype, change it's constructor, and all manner of such hacks. Nothing worked, but maybe I did it wrong (probable).

Peter Marks
  • 989
  • 2
  • 8
  • 15
  • Actually I just realized that this question is probably incorrectly phrased, it should maybe be: _"how to test whether a prototype chain was changed"_? – Peter Marks Jan 03 '12 at 05:25
  • ...and the only way I can think of is to hardcode every property for "Object", "Number", "Array", etc., and check that there is nothing outside of the known properties. Quite messy. Though I'd like to do this in a unit test to see that no one snuck something into the primitive types, which I've always been suspicious of (because it might blow up my code downstream and I would struggle to trace the problem). – Peter Marks Jan 03 '12 at 05:33
  • read this : http://www.3site.eu/doc/ – xkeshav Jan 03 '12 at 06:02
  • @PeterMarks — so how do you find a non-enumerable property that is part of the implementation but not ECMAScript (ed 3 or 5)? – RobG Jan 03 '12 at 06:02

1 Answers1

3

Just remove the obj.hasOwnProperty filter:

function isEmpty(obj) {
  for (var prop in obj) {
    return false;
  }
  return true;
}

DEMO

This way it will also tell you if contains any properties or if anything is in the prototype chain, if that's what you want.

Alternatively you can change

if (obj.hasOwnProperty(prop))

to

if (!obj.hasOwnProperty(prop))

if you only want to know if something is messing with it's prototype.

qwertymk
  • 34,200
  • 28
  • 121
  • 184
  • Could it be ...so simple and obvious? I wonder why my version of the function is the one most typically used (and recommended in dozens of answers on this very site). This indeed works, but I want to plug it into my tests to see if anything blows up unexpectedly. – Peter Marks Jan 03 '12 at 06:04
  • @PeterMarks: Generally `hasOwnProperty` is used to ignore properties that are inherited, but since you are interested in inherited props then the filter is counterproductive. – qwertymk Jan 03 '12 at 06:09
  • FWIW, JSlint complains when removing the ``hasOwnProperty`` check. Unsure why though. There is something more to this that I'm not getting. – Peter Marks Jan 03 '12 at 06:12
  • It will only test enumerable properties. ES 5 allows the addition of non-enumerable properties, so you still don't know if the object, or something in its prototype chain, has been modified. And what about objects that have enumerable properties (e.g. DOM elements)? – RobG Jan 03 '12 at 06:59
  • So I guess the real answer is that you can't tell for sure. Great. – Peter Marks Jan 03 '12 at 07:46