Enumerability and Ownership of JS Objects

JavaScript objects inherit properties from the object they descended from, and all objects descended from the JavaScript Object prototype. Objects can also have their own direct properties that do not exist higher up on the prototype chain. Direct and inherited qualifiers refer to the object ownership. The properties in the Object prototype are nonenumerable. Enumerable properties can be iterated over using a for..in loop. The for..in loop is a very useful but very nuanced tool.

Properties are either direct or inherited and they are enumerable or nonenumerable. You can detect and retrieve both, but you can only iterate over enumerable properties. For example, obj.toString is inherited and nonenumerable. It will not appear in a for..in loop unless it has been overwritten. Enumerability was set up so that the for..in loop can be used without unnecessary properties showing up.

If it isn't enough to iterate through your object using a for..in loop, there are some tools available to give you more options.

TOOLS:

obj.hasOwnProperty(property) returns true if the specified property is directly owned by the obj, enumerable or not.

Object.getOwnPropertyNames(obj) returns an array of property names for directly owned properties, enumerable or not.

Object.keys(obj) returns an array of keys for the directly owned, enumerable properties of the obj.

PRO TIPS:

Objects do not have a length property, but the arrays returned by the functions above do.

A for..in loop with a nested if-hasOwnProperty statement will iterate over directly owned, enumerable properties (it will skip inherited properties).

For..in loops cannot be depended upon to iterate over properties in order. This is why you should never use a for..in loop when iterating over an array where the index order is important.

During a for..in loop, if a property is modified in one iteration it may be visited a second time. If a property is deleted before it is visited, it will not be visited later. Properties added may or may not be visited. You should only modify the record you are currently accessing in the for..in loop while the loop is processing because the modified record may be visited once, twice, or not at all. Terrible things happen to wizards who meddle with time.

The final tip I'll share is how to iterate over an object with a for with semicolons loop. I recently needed to do this to stop the loop before the last property.

var obj = { a: 1, b: 2, c: 3 };  
var keys = Object.keys(obj);  
for (var i=0, count=keys.length; i < count; i++) {  
    alert(obj[keys[i]]);
};