1

I have an object and one of the properties is an array. I want to set a new property on that array (customProp = 0). However, I want to do so inside myObject's declaration.

myObject = {
  someString: "text",
  someArray: ["one","two"],
    /* What I've Tried */
    someArray: { customProp: 0 } // Overwrites my array with a new object
    someArray["customProp"]: 0 // Invalid syntax
    someArray: customProp: 0 // Also invalid
}

If I can't create the array then set a property on it, can I do so in one fell swoop (again, staying within the confines of this object)?



I have another (small) question: How can I reference one of the properties still inside the declaration. I want to set otherProp = someString, how would I do so?

myObject = {
  someString: "text",
  otherString: someString, // someString is undefined
  otherString: myObject["someString"], // myObject is undefined
  otherString: this["someString"] // Just... undefined
}

I may need to split this into a separate question, but hopefully whoever answers the first will know the answer to the second.

Gary
  • 13,303
  • 18
  • 49
  • 71

3 Answers3

3

Unfortunately neither of your requests are possible. Object literals in JavaScript are convenient but come with drawbacks, mostly what you've discovered.

When you are inside an object literal, the object doesn't quite exist yet. The JavaScript interpreter hasn't finished ingesting it. So inside the literal, this points to the object just outside the literal, and the literal has no way to refer to other parts of itself.

Fortunately, you can do both of what you want by just doing it after the literal declaration.

myObject = {
    someString: 'text',
    someArray: ['one', 'two']
};

myObject.someArray.customProp = 0;
myObject.otherString = myObject.someString;

Or if you want, you can wrap all of this inside a constructor function and create your object with new.

function MyObject() {
    this.someArray = ['one', 'two'];
    this.someArray.otherProp = 0;
    this.otherString = this.someString = 'text';
}

var myObject = new MyObject();
Matt Greer
  • 60,826
  • 17
  • 123
  • 123
  • I figured that was why it wasn't working, thanks for the confirmation. Surely there is a way to set a property while you're creating the object itself. If not, I'll use one of the two alternatives. (Those were what I was actually using before asking the question; I was just hoping for something more compact) – Gary Nov 12 '11 at 07:18
  • I think we'd all love to be able to do this. This is especially true with ExtJs, which relies heavily on object literals and you get bit by this all the time :-/ – Matt Greer Nov 12 '11 at 08:05
1

Well, arrays are numeric-based, so

someArray["customProp"]: 0

wouldn't work. It should be a Javascript Object {} for string-based keys to work. And then you could just say

someArray: {0:"one",1:"two","customProp":0},

For your second question: I don't think that's possible. The object is not yet initialized, so you can't yet read out of it...

Willem Mulder
  • 12,974
  • 3
  • 37
  • 62
  • 1
    There is no such thing as a JSON object http://benalman.com/news/2010/03/theres-no-such-thing-as-a-json/ – James Montagne Nov 11 '11 at 15:10
  • Javascript Object with JSON syntax, then ;) – Willem Mulder Nov 11 '11 at 15:29
  • It's an object literal. JSON's mirrors the object literal syntax. Very commonly misused term. – James Montagne Nov 11 '11 at 15:30
  • 1
    @Williem You can add arbitrary properties to an Array because it's an Object. However, it's not usually intended that way and will not work with prototype functions that use it's numeric properties (like sort). While it's a common mistake of developers new to JS, it does "work". – AutoSponge Nov 11 '11 at 15:51
  • @AutoSponge So then, internally, how is Array different from an object? Just the prototype functions that can be faster because they can assume some conditions (e.g. numeric keys)? – Willem Mulder Nov 11 '11 at 22:46
  • @Willem, let me add a correction without arguing semantics. If someArray had a property "cust" then accessing it like someArray["cust"] is perfectly valid. I will be using the typical array methods I can't have this value stored inside a numerical index. Not to mention using your example I'd have to get the value like myObject.someArray[3]["customProp"] which is a bit too clunky. – Gary Nov 12 '11 at 07:14
  • @Fantabulum I don't really understand what you mean... You mean that I incorrectly assumed that Arrays only work with numeric indici? In that case, yes you are right, but Arrays are still *meant* to work with numeric keys, and I think that the fact that an Array is an Object doesn't make it the perfect solution for storing objects the way you want to. Better just use a plain Object? – Willem Mulder Nov 12 '11 at 12:30
  • Yes, arrays are meant to work with numeric keys. I want the exact behavior of an array. I don't want my property inside one of the numeric keys. It's not meant to be one of my array elements, it's a property of the object itself. – Gary Nov 12 '11 at 17:51
  • Ok, then we are on one line :) – Willem Mulder Nov 14 '11 at 12:45
0

You can set properties on the Array but they will not get iterated using native functions. Your alternatives are an object (as suggested) or an array with an object as one of the members:

["one", "two", {customProp: 0}]
AutoSponge
  • 1,444
  • 10
  • 7
  • I want it to behave exactly as a standard array. The only difference is I want one custom property (specifically, it will remember which index I'm referencing). I'm aiming for this property to not be iterated through the prototype methods. – Gary Nov 12 '11 at 07:16
  • Then you can do that but you can't reference the array by property name in another property value. – AutoSponge Nov 13 '11 at 22:25