1

I use the following function to dynamically check the properties of a variable number of objects.

// FUNCTION: Check Objects
var ObjectsN = 4;
function CheckObjects()
{
        for (var i=0; i<=ObjectsN; i++)
        {
            if ((eval("Object"+i+".property")==0)
            {
                if (i==ObjectsN)
                {
                    alert("Function finished");
                }
            }
            else
            {
                return; // end function
            }
        }
}

I need to check if each object has the same property value.
Is there a way to do the same without using eval ? A real example would be really much appreciated.

cocoa coder
  • 214
  • 1
  • 3
  • 15

4 Answers4

3

The structure you're looking for is an Array. So use an array to store your objects:

/* assuming `var Object1 = new Object(), Object2 = new Object();` and so on */
var objs = [ Object1, Object2, Object3 ];

Then testing for a property should implement hasOwnProperty while iterating:

for (var o = 0; i < objs.length; o++){
  if (objs[o].hasOwnProperty('property')){
    // Property exists, test its value:
  }
}

You could then test against objs[o].property to retrieve its value and see if it matches what you're expecting.

And for those browsers that may not have the function available, here is a cross-browser version of hasOwnProperty (source, but originally from here):

/*
Cross-browser hasOwnProperty solution, based on answers from:
https://stackoverflow.com/questions/135448/how-do-i-check-to-see-if-an-object-has-an-attribute-in-javascript
*/
if ( !Object.prototype.hasOwnProperty ) {
  Object.prototype.hasOwnProperty = function(prop) {
    var proto = obj.__proto__ || obj.constructor.prototype;
    return (prop in this) && (!(prop in proto) || proto[prop] !== this[prop]);
  };
}
Community
  • 1
  • 1
Brad Christie
  • 100,477
  • 16
  • 156
  • 200
  • My objects are also variable, so I don't know how many are there. So should I tell each object (when it is created) to add itself to the objs array ? – cocoa coder Oct 16 '12 at 12:56
  • 1
    You can do that, yes. Assuming the `objs` (in this example) is global scope, you could place `objs.push(this)` in the object construct to maintain a list of objects that have been built. – Brad Christie Oct 16 '12 at 12:57
  • @cocoacoder: Here's an example of what I mean: http://jsfiddle.net/bradchristie/4Q8d5/1/ – Brad Christie Oct 16 '12 at 13:03
  • The alternative `hasOwnProperty` function is inappropriate here (and pretty awful in general), it will fail if the constructor property points to the wrong object, which is fairly common, or there is more than one object on the `[[Prototype]]` chain (other than `null`) which is also quite common. A much better alternative is [`propertyIsEnumerable`](http://ecma-international.org/ecma-262/5.1/#sec-15.2.4.7), which gives identical results in this case (but not for non–enumerable properties of course) and was the common solution for old Safari versions that were missing `hasOwnProperty`. – RobG Oct 16 '12 at 13:12
  • @BradChristie—that's ok, it wasn't your function. :-) – RobG Oct 16 '12 at 13:16
  • mh .. using ObjectsArray.push($(this.id)); only adds "object object" to the array, not the name of the object – cocoa coder Oct 16 '12 at 13:37
  • @cocoacoder: that's becase you're wrapping it in a jQuery object. You have to remember `el`!=`$(el)`; but `el`==`$(el)[0]`. – Brad Christie Oct 16 '12 at 15:12
  • @BradChristie OK, I got it working with the array ! However I still can't get it working with the array creation on the fly: for (var i = 1; i <= Objects; i++) ObjectsArray.push("Obj" + i) As the result is interpreted as a string, instead of objects – cocoa coder Oct 16 '12 at 16:49
  • @cocoacoder: Take a look at the jsfiddle I posted and how the object (at the bottom) automatically adds the new objects to an array. Also, look at the `for` statement and how I iterate over the list of objects that have been stored. – Brad Christie Oct 16 '12 at 17:42
2

assuming Object0, Object1, Object2,Object3 & Object4 are global variables.

you could access the variables by using window

var ObjectsN = 4;
function CheckObjects()
{
    for (var i=0; i<=ObjectsN; i++)
    {
        if (window['Object'+i].property == 0)
        {
            if (i==ObjectsN)
            {
                alert("Function finished");
            }
        }
        else
        {
            return; // end function
        }
    }

}

Neverever
  • 15,890
  • 3
  • 32
  • 50
  • I would also include `if (window['Object'+i] && window['Object'+i].property == 0)` in case the object is null or undefined – andres descalzo Oct 16 '12 at 12:55
  • @andres yes indeed, but that's up to the OP to do the checking – Neverever Oct 16 '12 at 12:57
  • so with this method I don't have to use an array ? Only adding window with brackets, right ? – cocoa coder Oct 16 '12 at 13:00
  • yes, this solution requires no array. However, for best practice or readability, `Array` solution is recommended. – Neverever Oct 16 '12 at 13:04
  • 1
    I'm not expert in evaluating JavaScript performance, however, if your number of variables is going to be large (100+), `Array` solution is strongly recommended, if you are doing experiment/proof of concept/debugging, then stick to `window` – Neverever Oct 16 '12 at 13:08
1

Whenever you are thinking about numbering variables. Use an array instead.

Don't have Object1, Object2, etc. Have [ x, y, x ]

Then you can do:

for (var i = 0; i < objects.length; i++) {
    var obj = objects[i];
    if ("property" in obj) {
        // Whatever
    }
}
Quentin
  • 914,110
  • 126
  • 1,211
  • 1,335
1

Similar to Neverever's answer, but passing a reference to the global object instead of assuming there's a window object available.

var ObjectsN = 4;
var CheckObjects = (function(global) {

    for (var i=0; i<=ObjectsN; i++) {
        if ( global['Object' + i].property == 0) {
            if (i == ObjectsN) {
                alert("Function finished");
            }
        } else {
            return; // end function
        }
    }
}

Are you sure that == 0 is the test you want? That will return true even if the property doesn't exist. The function isn't particularly robust, if an object from 0 to n doesn't exist, an error will be thrown.

The function will continue only as long as Objectn.property == 0 returns true, so it will exit as soon as it gets a truethy result (e.g. Object0.property = 'foo').

RobG
  • 142,382
  • 31
  • 172
  • 209
  • thanks for your answer, so should I add (as previously suggested) `if (global['Object'+i] && global['Object'+i].property == 0)` to make sure the object exists ? – cocoa coder Oct 16 '12 at 13:09
  • also do you consider using global or an array better for performance? – cocoa coder Oct 16 '12 at 13:14
  • Performance difference is trivial, much better to use an array, see Brad's answer. – RobG Oct 16 '12 at 13:21
  • thanks. BTW: I think the else block isn't redundant as it exits the function without having to continue the for statement if one object has already another value than 0. Right? – cocoa coder Oct 16 '12 at 13:22
  • `if (global['Object'+i] && global['Object'+i].property == 0)` is better. Yes, the `else` block does something, I read the test backwards initially. – RobG Oct 17 '12 at 01:20