Having this code
var a = {date : 12};
for(var t in a){
alert(t);
}
I have one alert with date property.
But everywhere (i.e. here) i see that it is needed to write :
for (var property in object) {
if (object.hasOwnProperty(property)) {
// do stuff
}
}
So why i don't see internal properties of object?
The for..in syntax iterates every property of the object, including those found on the prototype chain (if they are enumerable). This is usually not what you want, so the hasOwnProperty check is usually recommended.
In your case it's not necessary, as your plain object doesn't inherit any enumerable properties from the Object prototype (the only thing in its prototype chain)
Also, for..in gives you the property names (keys) of the object, if you're interested in the value of that particular property, you have to use the bracket notation, extending your example to this:
var a = {date : 12};
for(var t in a){
alert(a[t]);
}
In JavaScript there exists the 'prototype chain', a form of inheritance. If you were to add a property to the prototype of a, and then add your date property directly onto a, your for loop would find both those properties.
The hasOwnProperty checks whether the current property has been attached directly to the context object or whether it has been inherited through the prototype chain.
So in my example, if you had added a property to a's prototype, the hasOwnProperty condition would return false and you wouldn't "do stuff" with it.
I guess the best way to see it is through an example:
Object.prototype.aBaseProperty = 123;
var childObject = { date: 12 };
for (var property in childObject) {
console.log(property)
}
// output: date aBaseProperty
for (var property in childObject) {
if (childObject.hasOwnProperty(property)) {
console.log(property)
}
}
// output: date
Also, rather than doing the hasOwnProperty check, you might prefer
Object.keys(object).forEach(function(value, key) { ... });
Where Object.keys will only return own properties.
Related
On MDN (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/hasOwnProperty), I saw snippet like this:
var buz = {
fog: 'stack'
};
for (var name in buz) {
if (buz.hasOwnProperty(name)) {
console.log('this is fog (' + name + ') for sure. Value: ' + buz[name]);
}
else {
console.log(name); // toString or something else
}
}
In the snippet, console.log(name); // toString or something else looks a bit confusing to me. I understand toString is a property of Object.prototype and this property can be accessed by buz.toString.
However, when I run the snippet in Chrome, I didn't saw the toString property is printed (console.log), though the comments say it should be iterated by for..in and printed..
Does anyone have ideas about why the properties from one's prototype can't be iterated by "for..in"?
for x in obj iterates over only enumerable properties of the object (including those on the prototype). A given property can be marked as enumerable or not. So, if for/in is skipping some property, then that is likely because that property is not configured as enumerable.
See working demo here: http://jsfiddle.net/jfriend00/gyc9gnmj/ that shows how only enumerable properties are iterated with for x in obj.
And, in fact, you can see that the toString() method is marked as enumerable: false with this code:
function log(x) {
document.write(JSON.stringify(x));
}
var buz = {
fog: 'stack'
};
log(Object.getOwnPropertyDescriptor(Object.getPrototypeOf(buz), "toString"));
Just to shed more light in continuation with what jfriend00 has already answered, Object's data properties in JavaScript has four attributes namely [[configurable]], [[enumerable]], [[writable]] and [[value]] all of which is set to for the former three the default value is true and for the last it defaults to undefined.
Say suppose there exists a need where you would like to avoid a property's value not to be returned in a for-in loop. You can write as
var car = {};
Object.defineProperty(car, 'name',{
enumerable : false,
value : 'BMW'
});
It is recommended to always use hasOwnProperty, but in many cases this is not needed.
For example consider the following code:
var object = JSON.parse(somejsontext);
for(var prop in object) {
console.log(object[prop]);
}
I know in this case that prop is part of the object, it is explict define by the for..in.
But according to MOZ https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/hasOwnProperty we should use it to avoid iterating over non-enumarable props, with this example:
var buz = {
fog: 'stack'
};
for (var name in buz) {
if (buz.hasOwnProperty(name)) {
console.log('this is fog (' + name + ') for sure. Value: ' + buz[name]);
}
else {
console.log(name); // toString or something else
}
}
But testing this code actually, never goes to the else.
So when does make sense the use of hasOwnProperty ?
UPDATE: Considering the choosen answer, we can safetly avoid the use of hasOwnProperty in this cases:
- Object js has not been extended by any javascript library or by our code
- Object is a simple code that we have control on
The problem arises when a prototype includes enumerable properties that your code did not anticipate. For example, suppose this ran just before your example:
Object.prototype.foobar = "hello";
In this case, iterating over buz would include the enumerable foobar prototype property. This hasOwnProperty pattern allows your code to differentiate between properties that are directly on the object, versus properties that are inherited from a prototypal ancestor.
The problem is not "enumerating over non-enumerable properties" (that's by definition not possible, unless you explicitly get them via getOwnPropertyNames for each level of the prototype hierarchy), but rather enumerating over inherited properties. This is a concern when using libraries that may add enumerable properties to high-level prototypes, exactly as I have illustrated above.
If you want to add a property to a prototype without causing that property to be enumerated, you can make a non-enumerable property with Object.defineProperty:
Object.defineProperty(Object.prototype, "foobar", {
value: "hello",
enumerable: false,
writeable: true,
configurable: true
});
Such a property would not appear in a for..in loop on buz (or in a for..in loop directly on Object.prototype, either).
Given this object:
var myObject = {
...
};
Is this method:
var hasProp = Object.keys(myObject).indexOf('myProp') !== -1;
The same as:
var hasProp = myObject.hasOwnProperty('myProp')
That is, will they result in the same value for hasProp, always?
I was asked this in an interview and the interviewer said they would yield different results but did not give me an example.
Thanks!
Any non-enumerable property breaks this symmetry. For example, fire up a Node.js console or use a compliant browser's console to perform both:
Object.keys([]); // yields []
[].hasOwnProperty('length'); // yields true.
because for arrays, the magic length property is marked as non-enumerable. There is another function which does all of them, even non-enumerables:
Object.getOwnPropertyNames([]) // yields [ 'length' ]
that is fully equivalent.
Object.keys "returns an array of a given object's own enumerable properties". hasOwnProperty works regardless of the fact that the property is enumerable or not.
See this example where hasOwnProperty is true yet Object.keys does not contain the property.
var obj = {};
Object.defineProperty(obj, "prop", {value: 1, enumerable: false});
obj.prop; // 1
obj.hasOwnProperty("prop"); // true
Object.keys(obj); // []
Object.keys(obj).indexOf('prop'); // -1
This uses the ECMAScript 5 defineProperty but non-enumerable properties also exist on basic objects. As shown by #ChrisDrost, the array's length is a non-enumerable property that does not show up in Object.keys yet responds true to hasOwnProperty.
Your code will not always return the same value for hasOwnProperty.
From Mozilla's Documentation on hasOwnProperty:
Example: Direct versus inherited properties
The following example differentiates between direct properties and
properties inherited through the prototype chain:
o = new Object(); o.prop = 'exists'; o.hasOwnProperty('prop'); // returns true
o.hasOwnProperty('toString'); // returns false
o.hasOwnProperty('hasOwnProperty'); // returns false
Which means that your method acts as a sort of hasOwnProperty that also checks for inherited attributes.
I think in practice, they act the same, but this a subtle difference.
Here is a jsFiddle of my question: http://jsfiddle.net/4wyvv/1/
Basically:
//constructor function
function Maker(){
var str;
this.init = function(str){
this.str = str;
};
this.msg = function(){
return this.str;
};
}
//object from Maker
var obj = new Maker();
obj.init("Hi my name is Dan");
//make sure everything exists and has worked as expected
Audit.Log(obj.msg());
//look in Maker.prototype for the constructor property
Audit.Log(obj.constructor);
//look in Maker.prototype for the constructor property
Audit.Log(Maker.prototype.constructor);
//now look for all makers prototype properties, this should list atleast "constructor"
for(var i in Maker.prototype){
Audit.Log(i);
}
Why does the foreach loop not put out anything? It should at least put out constructor as I showed that Maker.prototype.constructor exists.
Some properties of object like "constructor" are hidden or to be more precise non-enumerable so they are not enumerated using a for in loop like this, In ECMA5 we have a method that can get all the properties
Object.getOwnPropertyNames(Maker.prototype)
this is give you
["constructor"]
Here is a detailed explanation : How to display all methods of an object in Javascript?
From MDN
for..in Iterates over the enumerable properties of an object, in
arbitrary order. For each distinct property, statements can be
executed.
Things like constructor, toString, hasOwnProperty are non enumerable properties and they won't be listed in for..in
I have an object with various properties. The name of the object is a global variable but the properties are changed at runtime by methods. Some methods add properties to the object. I'd like to add a method that loops through this object and removes all of its properties that are either null or empty. I could check each property by specifying its name and checking its state but if I add properties later, I'd have to update this cleanup method too. How can I loop through the properties of an object without know the name of the properties first.
Thanks for your suggestions.
Iteration over an object is simple - the for in loop:
for (var key in object) {
if (object.hasOwnProperty(key)) {
//Now, object[key] is the current value
if (object[key] === null || isEmpty(object[key]))
delete object[key];
}
}
isEmpty doesn't exist, you have to define it or replace it with something more meaningful, I couldn't understand what you meant by empty in your question.
I use object.hasOwnProperty because objects inherit things from Object.prototype and possibly other places (arrays for example inherit from Array.prototype, which inherits from Object.prototype). So:
object.toString; //function toString() { [native code] }
But, object.toString actually refers to Object.prototype.toString - it isn't really in your object, but when you type object.toString, the interpreter sees that there's no object.toString, so it checks up the prototype chain until it finds it.
hasOwnProperty checks if a key actually exists on an object:
object.hasOwnProperty("toString"); //false
object.foo = "bar";
object.hasOwnProperty("foo"); //true
Subscript access to objects is also simple:
var object = {foo: "bar"};
object.foo; //"bar"
object["foo"]; //"bar"
var key = "foo";
object[key]; //"bar"
Note that whatever is passed to the brackets gets converted to a string. So, for example, you can do this:
object[Object.prototype.toString] = "magic";
Object.keys(object); //["function toString() { [native code] }"]
In case you're wondering, Object.keys is an ES5 (EcmaScript 5) feature.
You can use a for each loop to iterate through the object properties.
for ( var i in obj ) {
if ( obj[i] === null ) {
delete obj[i];
}
}