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];
}
}
Related
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.
Can you explain me this?
JAVASCRIPT
if (typeof Array.prototype.contains != 'function') {
Array.prototype.contains = function (str){
return this.indexOf(str) > -1;
};
}
var text = "Hello world";
var tokens = text.split(" ");
console.log(tokens.length);
for (var i in tokens){
console.log(tokens[i]);
}
OUTPUT
2
"Hello"
"world"
function ()
In other words, the "contains" function i added to the Array prototype appears in the for loop as last element (but the array length is 2). Why?
Why?
Because for-in doesn't loop through array entries, it loops through enumerable properties of an object. You've created a new enumerable property on Array.prototype, and so that property shows up in for-in loops on any array.
The solutions are:
Don't do that, instead loop through arrays in any of several ways that don't have that problem, or
Use hasOwnProperty to filter out inherited properties (see link above for more), or
Define contains as a non-enumerable property via Object.defineProperty or similar (you can only do this on ES5+ engines, it cannot be shimmed).
I'm attempting to loop through an object and use different functions on each different sub-object based on it's type. instanceof seemed to be the only way to identify non-built in types, so I attempted to use it with for...in; however, I'm not getting the expected output.
Here is a sample fiddle to illustrate my issue: http://jsfiddle.net/zv230dvL/2/
function testObject(){}
function testContainer(objects){
this.zero = objects[0];
this.one = objects[1];
this.two = objects[2];
}
var singleObject = new testObject();
var container = new testContainer(
[new testObject(),
new testObject(),
new testObject()]
);
...
//Testing if a single object functions as expected
out(singleObject instanceof testObject);
//Testing if directly referencing an object
//in a container functions as expected
out(container.zero instanceof testObject);
//iterating through a container object...
for(i in container){
out(i instanceof testObject);
}
The output is
true
true
false
false
false
First, what would be the appropriate method to do something like this?
Second, why does the variable in the for...in loop behave in this manner?
no jQuery please.
When you iterate an Object with for..in, the loop variable will have the key, in string type. So, you should be checking like this
for (i in container) {
out(container[i] instanceof testObject);
}
Now, you are using the object corresponding to the key i in container. With this change, all the items will evaluate to true.
Note: for..in is supposed to give all the inherited properties as well. So, the normal looping pattern when you use for..in with an Object is
for (i in container) {
if (container.hasOwnProperty(i)) {
out(container[i] instanceof testObject);
}
}
This will make sure that, only the properties which are directly defined in the object are checked.
I am a newbie in Javascript and trying to learn this language. After going through several posts I figured out that in order to check an Object's particular property we can broadly use one of the following methods.
1] Using hasOwnProperty
Object.hasOwnProperty("propertyName")
However this does not check properties inherited from the Object's prototype chain.
2] Loop over all the properties and check if property exists.
for(propertyName in myObject) {
// Check if "propertyName" is the particular property you want.
}
Using this you can check Object's properties in the prototype chain too.
My question is: Is there a method other than 2] by which I can check if "propertyName" is a property in Object's prototype chain? Something similar to "hasOwnProperty" and without looping?
You can just check the property directly with in, and it will check the prototype chain as well, like this
if ('propertyName' in myObject)
an example
var obj = function() {};
obj.prototype.test = function() {};
var new_obj = new obj();
console.log( 'test' in new_obj ); // true
console.log( 'test22222' in new_obj ); // false
console.log( new_obj.hasOwnProperty('test') ); // false
FIDDLE
Reflect.has can make a work for you
console.log(Reflect.has({}, 'toString')); // true
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