-2

I want to set two elements in an object equal to one string. I could do it on two separate lines, like this.

var strings =
{
    "1": "string 1",
    "01": "string 1"
}

But I would rather it be on one line though, like this.

var strings =
{
    "1", "01": "string 1"
}

That obviously does not work. Is there a way to write it so that both elements are equal to that one string?

Caleb
  • 21
  • 5
  • 6
    There are no arrays in your question. – Mark Jan 04 '19 at 22:16
  • what's your use case? is it mapping all the keys "1", "02", "3", "2" to values that are programmable like "string 1"? – ehacinom Jan 04 '19 at 22:18
  • 1
    That there is a json object, not an array. Well the first one is, the second one is not valid. – basic Jan 04 '19 at 22:19
  • is it "1, 01" or "1", "01" , as later is not a valid object key – Naga Sai A Jan 04 '19 at 22:19
  • @Caleb there is an object, not an array. Array looks like `[1, 2]` and has no keys. – Dawid Zbiński Jan 04 '19 at 22:20
  • I want it to be "1", "01", but I know it is not valid. I was wondering if there was an alternative to that that allowed both of those elements to be equal to "string 1." – Caleb Jan 04 '19 at 22:20
  • In JavaScript (unlike Java) literal arrays are within **square** brackets. – PM 77-1 Jan 04 '19 at 22:21
  • 1
    Well, if it's just "1" and "01" you should definitely use integer as a key and take the values by integer values too. – Dawid Zbiński Jan 04 '19 at 22:21
  • @ Dawid Zbinski I don't understand what you're telling me. Sorry, I'm pretty bad with Javascript terminology – Caleb Jan 04 '19 at 22:22
  • 2
    Please explain why the first object is not suitable for you: they *have* the same string. Strings are immutable and chances are that JavaScript does not even allocate memory for them twice. So what is exactly the issue? – trincot Jan 04 '19 at 22:25
  • You are not really providing enough information to give a complete answer. E.g. Should both properties always have the same value? I.e. if `strings['1']` is assigned a new value, should `strings['01']` also change? – Felix Kling Jan 04 '19 at 22:33
  • @trincot It was not a huge problem, I was just wondering if I could squish it into one line like the second example I gave – Caleb Jan 04 '19 at 22:35
  • @Felix Kling Yes, both of them should have the same value all the time – Caleb Jan 04 '19 at 22:35
  • 1
    @Caleb, that is crucial information and you should add an example in your question illustrating the desired behaviour when a new string is assigned to one of the two properties. – trincot Jan 04 '19 at 22:36
  • So when I do `strings['1'] = "foo"` you expect `strings['01']` to magically also return `"foo"` (and vice versa)? Does the code that performs the assignment know about this restriction? Or does this need to happen transparently, i.e. without the code performing the assignment knowing the relationship between `1` and `01`. As trincot said, this is crucial information, and doesn't really have anything to do with "writing it in one line". – Felix Kling Jan 04 '19 at 22:37
  • I did not word my question right. I was trying to avoid writing out "string 1" twice. I was hoping I could do it while just writing "string 1" once – Caleb Jan 04 '19 at 22:40
  • So you do not want the properties be in sync automatically. – Felix Kling Jan 04 '19 at 22:44
  • I was hoping they would sync automatically. – Caleb Jan 04 '19 at 22:48
  • Kind of like the way I had it in my second example. They are equal to each other, no matter what the value of it is – Caleb Jan 04 '19 at 22:49
  • @Caleb Hey, I was just about to add my answer when this got closed, so I added my answer to the dup: https://stackoverflow.com/questions/13104949/can-one-set-multiple-properties-inside-an-object-literal-to-the-same-value/54047241#54047241 – Matías Fidemraizer Jan 04 '19 at 22:53
  • No, every property has it's own copy of the value. I had deleted something from my answer because I thought it's not what you want but I will add it back and you can let me know if that's the behavior you are looking for. – Felix Kling Jan 04 '19 at 23:04

4 Answers4

1

You could take a Proxy and normalize the keys to a numerical value without leading zeroes.

var p = new Proxy(
        { 1: 'string 1' },
        {
            get: function(obj, prop) {
                return prop in obj
                    ? obj[prop]
                    : obj[+prop];
            }
        }
    );

console.log(p['1']);
console.log(p['01']);
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
1

But I would rather it be on one line though, like this.

JavaScript doesn't care about line breaks. You can write it all in one line:

var strings = { "1": "string 1", "01": "string 1"};

On a more serious note, if you simply want to avoid repeating the value (e.g. to avoid typos when refactoring), then the simplest solution would be to store the value separately in a variable:

const value = "string 1";
var strings =
{
    "1": value,
    "01": value,
};

If it is the assignment that you don't like duplicating, you could use the fact that an assignment returns the assigned value:

var strings = {};
strings['1'] = strings['01'] = "string 1";

Both if these express the intend in simple and clean ways. Don't try to be too clever, keep it simple.


From the comments however it seems like you want the values of both properties to be "in sync". This is not possible with "normal" property assignment. Doing strings[1] = "new value"; will not change the value of strings['01'].

To do this you need to use getters and setters (alternatively you can use proxies).

var strings = (function() {
  var value = "string 1";
  var obj = {};
  ['1', '01'].forEach(prop => Object.defineProperty(obj, prop, {
    get: () => value,
    set: v => value = v,
    enumerable: true,
  }));
  return obj;
}());

console.log(strings['1'], strings['01']);

strings['1'] = 'foo';
console.log(strings['1'], strings['01']);

strings['01'] = 'bar';
console.log(strings['1'], strings['01']);
Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
0

You could add a function in the second entry as more or less a callback to the object itself. This requires accessing it as a function though, not a param.

var strings = {
    "One": "string 1",
    "Two" : function(){ return this.One;}
}

console.log(strings.One);
console.log(strings.Two());

strings.One = "Waffle"
console.log(strings.Two());

The only difference is you have to access the parameter as a function call.

Edit:

Added an example with Getter to negate calling as function.

var strings = {
    "One": "string 1",
    get Two(){ return this.One;}
}

console.log(strings.One);
console.log(strings.Two);

strings.One = "Waffle"
console.log(strings.Two);
basic
  • 3,348
  • 3
  • 21
  • 36
0

I think this is what you are looking for:

var str = "string 1";

var obj = {"1": str, "01": str};

console.log(obj);

{ '1': 'string 1', '01': 'string 1' }