First of all, you need to improve your understanding of these languages and learn the correct terminology.
- There is no (single) language named "Javascript" at all. You are implicitly using several languages here (depending on the runtime environment), all of which are ECMAScript implementations, and one of which is Netscape/Mozilla JavaScript (in Mozilla-based software like Firefox).
- An object does not have variables, it has properties (not: keys). Global code, function code, and
eval
code can have variables; that is a different (but similar) concept.
- The function is not getting an object, it is being passed a reference to an object as argument.
As a programmer, you should already know that you can do repetitive tasks in a loop; the associated statements in ECMAScript implementations are for
, for
-in
, while
and do
. So you do not have to write several if
statements.
You can access the properties of an object in two ways, where property
is the property name:
- Dot notation:
obj.property
- Bracket notation:
obj["property"]
The second one is equivalent to the first if the property name is an identifier, i.e. if it follows certain naming rules. If the property name is not an identifier or if it is variable, you have to use the second one. This also shows that all property names are string values. So you can store the name of a property as value of a variable or another property, and then access the variable or property in the property accessor. In the following, a property name (property
) is stored in and used from a variable:
var propertyName = "property";
obj[propertyName]
Combining that with a loop allows you to iterate over certain properties of an object. Unfortunately, the solutions presented so far are flawed in two respects: A for
-in
statement iterates only over the enumerable properties of an object, and it does so in arbitrary order. In addition, it also iterates over the enumerable inherited properties (which is why one solution requires the hasOwnProperty()
call).
A simple, sure and efficient way to iterate only over certain properties of an object in a defined order looks as follows:
var propertyNames = ['name1', 'name2', 'name3'];
for (var i = 0, len = propertyNames.length; i < len; ++i)
{
/* … */ myObject[propertyNames[i]] /* … */
}
This works because propertyNames
refers to an Array
instance, which encapsulates an array data structure. The elements of an array are the properties of the Array
instance that have integer indexes from 0 to 65535 (232−1). Because indexes are not identifiers (they start with a decimal digit), you have to use the bracket property accessor syntax (some people misunderstand this and refer to all ECMAScript objects as "arrays", even call them "associative arrays" and […]
the "Array operator"). Therefore, propertyNames[i]
evaluates to the values of the elements of the array in each iteration as i
is increased by 1 each time. As a result, myObject[propertyNames[i]]
accesses the property with that name in each loop.
Now, to find out whether the property is set, you need to define what that means. Accessing a property that does not exist results in the undefined
value (not in an error). However an existing property may also have the undefined
value as its value.
If "not set" means that the object does not have the property (but may inherit it), then you should use hasOwnProperty()
as used in Mahn's solution.
If "not set" means that the object does not have the property and does not inherit it, then you should use the in
operator, provided that the object is not a host object (because the in
operator is not specified for them):
if (propertyNames[i] in obj)
If "not set" means that the object either has or inherits the property, but the property has the undefined
value, or the object neither has nor inherits the property, then you should use the typeof
operator as used in Bob Davies' and aetaur's solutions (but the latter approach using Array.prototype.every()
is less compatible as-is; that method was not specified before ECMAScript Edition 5, and is not available in IE/JScript < 9).
There is a third option with ECMAScript Edition 5.x, the Object.keys()
method which (despite its name) returns a reference to an Array
instance that holds the names of all not-inherited properties of the argument:
var propertyNames = Object.keys(obj);
/* continue as described above */
It is a good idea to emulate Object.keys()
if it is not built-in, as this algorithm is frequently useful.