1

Suppose I create a custom object/javascript "class" (airquotes) as follows:

// Constructor
function CustomObject(stringParam) {
  var privateProperty = stringParam;

  // Accessor
  this.privilegedGetMethod = function() {
    return privateProperty;
  }

  // Mutator
  this.privilegedSetMethod = function(newStringParam) {
    privateProperty = newStringParam;
  }
}

Then I want to make a list of those custom objects where I can easily add or remove things from that list. I decide to use objects as a way to store the list of custom objects, so I can add custom objects to the list with

var customObjectInstance1 = new CustomObject('someString');
var customObjectInstance2 = new CustomObject('someOtherString');
var customObjectInstance3 = new CustomObject('yetAnotherString');

myListOfCustomObjects[customObjectInstance1] = true;
myListOfCustomObjects[customObjectInstance2] = true;
myListOfCustomObjects[customObjectInstance3] = true;

and remove custom objects from the list with

delete myListOfCustomObjects[customObjectInstance1];

but if i try to iterate through the list with

for (i in myListOfCustomObjects) {
  alert(i.privilegedGetMethod());
}

I would get an error in the FireBug console that says "i.privilegedGetMethod() is not a function". Is there a way to fix this problem or an idiom in javascript to do what I want? Sorry if this is a dumb question, but I'm new to javascript and have scoured the internet for solutions to my problem with no avail. Any help would be appreciated!

P.S. I realize that my example is super simplified, and I can just make the privateProperty public using this.property or something, but then i would still get undefined in the alert, and I would like to keep it encapsulated.

6
  • I am not quite sure what you are trying to accomplish here, but your code shouldn't and wouldn't work, since you have syntax errors there. Specifically in the way you call to constructor with [] instead of (). Commented Nov 4, 2011 at 20:51
  • sorry, that was a typo. i fixed the brackets Commented Nov 4, 2011 at 20:58
  • basically i'm looking for a way to create a list of custom objects and iterate through them while maintaining access to their privileged methods. Commented Nov 4, 2011 at 21:08
  • Why are you trying to make the custom objects indices of your array then? Just put them in array like so: array.push(customObject); and then iterate over the array using the standard for loop. Commented Nov 4, 2011 at 21:10
  • I was trying to stay away from arrays since i didn't know of an easy way to remove an item by value (i'd have to iterate through the array, right?). with objects, i can do easy checks to see if something exists with "if (something in object)". Commented Nov 4, 2011 at 21:20

3 Answers 3

1

i won't be the original object as you were expecting:

for (i in myListOfCustomObjects) {
    alert(typeof i); // "string"
}

This is because all keys in JavaScript are Strings. Any attempt to use another type as a key will first be serialized by toString().

If the result of toString() isn't somehow unique for each instance, they will all be the same key:

function MyClass() { }
var obj = {};

var k1 = new MyClass();
var k2 = new MyClass();

obj[k1] = {};
obj[k2] = {};

// only 1 "[object Object]" key was created, not 2 object keys
for (var key in obj) {
    alert(key);
}

To make them unique, define a custom toString:

function CustomObject(stringParam) {
    /* snip */

    this.toString = function () {
        return 'CustomObject ' + stringParam;
    };
}

var obj = {};
var k1 = new CustomObject('key1');
var k2 = new CustomObject('key2');

obj[k1] = {};
obj[k2] = {};

// "CustomObject key1" then "CustomObject key2"
for (var key in obj) {
    alert(key);
}

[Edit]

With a custom toString, you can set the object as the serialized key and the value to keep them organized and still continue to access them:

var customObjectInstance1 = new CustomObject('someString');
var customObjectInstance2 = new CustomObject('someOtherString');
var customObjectInstance3 = new CustomObject('yetAnotherString');

myListOfCustomObjects[customObjectInstance1] = customObjectInstance1;
myListOfCustomObjects[customObjectInstance2] = customObjectInstance2;
myListOfCustomObjects[customObjectInstance3] = customObjectInstance3;

for (i in myListOfCustomObjects) {
  alert(myListOfCustomObjects[i].privilegedGetMethod());
}
Sign up to request clarification or add additional context in comments.

4 Comments

ah, that was what i was wondering. so they all get converted to strings? so what's the best way to create a list of custom objects and iterate through them with access to their privileged methods?
@user1030342 You can associate them with their unique serialization by setting them as the value rather than just true. See my edit for an example.
ok, now i'm getting a weird error. if i just do one privileged method, it works great! but, when i have more than one, the first privileged method works fine, but then the rest get a "myListOfCustomObjects[i] is undefined" error. i swapped the order and the first one always works fine, but then the rest get that error. am i missing something again?
Strange, when i do alert, i get the aforementioned error, but if i do console.log, i don't get an error. Well, i think i got it working for the most part. Just to review, all keys within an object become strings, but values can be anything, yes? Thanks for the help!!
1

The for iteration variable is just the index, not the object itself. So use:

for (i in myListOfCustomObjects) {
  alert(myListOfCustomObjects[i].privilegedGetMethod());
}

and, in my opinion, if you use an Object as an array index / hash, it just would be converted to the string "Object", which ends up in a list with a single entry, because all the keys are the same ("Object").

2 Comments

Simply incorrect. Object passed as an index to an array most certainly won't get converted to the string 'Object' and create a list with one element - it will however create a property "[object Object]" on array object.
Right, don't I want to iterate through the index and not the value? The value in each key/value pair will just be true. I'm assuming my list object is looking something like {CustomObject1: true, CustomObject2: true}
1
myListOfCustomObjects =[ 
            new CustomObject('someString'),
            new CustomObject('someOtherString'),
            new CustomObject('yetAnotherString')
]

you will get access to any element by index of array.

1 Comment

if i do end up having to use arrays, what's the best way to remove an object from the list. say if i want to remove CustomObject('yetAnotherString') from the list, what would be the best way to remove it?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.