33

For example, can I do this?:

{ 
   a: b: c: d: 1,
   e: 2,
   geh: function() { alert("Hi!") }
}

EDIT: Is there some way I can avoid doing this?:

{ 
   a: 1,
   b: 1,
   c: 1,
   d: 1,
   e: 2,
   geh: function() { alert("Hi!") }
}
PitaJ
  • 12,969
  • 6
  • 36
  • 55

7 Answers7

30

An update to this (in terms of the latest JavaScript abilities) avoiding unwanted defined vars:

{
  let v;
  var obj = {
     "a": (v = 'some value'),
     "b": v,
     "c": v
  };
}

This will mean v won't be defined outside the block, but obj will be.

Original answer

Another way of doing the same thing is:

var v;
var obj = {
     "a": (v = 'some value'),
     "b": v,
     "c": v
};
Pebbl
  • 34,937
  • 6
  • 62
  • 64
  • This solution is great. It also works when the object is anonymously defined, e.g. as a direct parameter when calling a function. – Jpsy Oct 28 '15 at 13:53
15

You could set a line of equality between various properties:

var foo = {};
foo.a = foo.b = foo.c = "Hello";

Or you could just create a method that does the mass-assignment for you:

var foo = {
    setValue: function( props, value ) {
        while ( props.length ) this[ props.pop() ] = value;
    }
}

foo.setValue( [ "a", "b", "c" ] , "Foo" );
Sampson
  • 265,109
  • 74
  • 539
  • 565
  • Your first example won't work. You'll get a *TypeError* because `foo` has not yet been assigned the object, so it still has the `undefined` value. – I Hate Lazy Oct 27 '12 at 23:24
  • 3
    @user1689607 I was shocked that it worked when I was hacking around in my console; apparently I forgot I had already declared `foo` with an `a` property prior to running that code. – Sampson Oct 27 '12 at 23:26
  • 1
    I've made the same mistake in the console. – I Hate Lazy Oct 27 '12 at 23:30
3

You could try this. It's not the syntactic sugar you're looking for (eg. {a,b,c:1, d:2}) but it's another way to do it, although all of these answers are pretty much fine.

(object,fields,value)=>Object.assign(object||{}, ...fields.map(f=>({[f]:value}) ))

Explanation:

(object,fields,value)=>

Takes an object (or falsey value if you want a new object, feel free to rearrange the argument order)

Object.assign(object||{},

Will return an object based on object and it will mutate the object. To disable this, simply add a first argument object literal like this Object.assign({}, object || {}, ...

...fields.map(f=>({[f]:value}) )

Will spread the array of fields mapped to objects as a list of extra arguments to Object.assign. ['a','b'].map(f=>({[f]:value}) ) will give [{a:value}, {b:value}] and f(...[{a:1},{b:1}]) is like f({a:1},{b:1}). Object.assign does the rest :)

M3D
  • 673
  • 6
  • 11
2

There's yet another approach: using a mapping function...

// This will be standard! 
if (!Object.fromEntries)
  Object.fromEntries = entries => entries.reduce ((o, [key, value]) => ({
     ...o,
     [key]: value
  }), {})


const setSameValue = (source, props, value) => ({
  ...source,
  ...Object.fromEntries (
     props.map (prop => [prop, value])
  )
})

// The important part: do what you want with ease!
const output = setSameValue ({}, ['1', '01'], 'string 1')

const obj = { x: 1, y: 'hello' }

const output2 = setSameValue (obj, ['1', '01'], 'string1')

console.log ('output1:', output)
console.log ('output2:', output2)
Matías Fidemraizer
  • 63,804
  • 18
  • 124
  • 206
1

You could wrap in a closure too, if you didn't want multiple local vars. This syntax seems to be popular (but ugly):

var obj = (function() { var v='some value'; return { a:v, b:v, c:v }; })();
raider33
  • 1,633
  • 1
  • 19
  • 21
0

Use for of loop instead.

for (let [key, value] of Object.entries(object_name)) {
        object_name[key] = 0; // the value that you want to assign
      }
Mahmud hasan
  • 918
  • 10
  • 13
0

Or yet another way:

{...['a', 'b', 'c', 'd'].reduce((obj,prop)=>({...obj, [prop]: 1}), {}) }

It can be wrapped up pretty neatly by extending the Array prototype:

Array.prototype.ditto = function(v) { return this.reduce((o,p)=>({...o, [p]: v}), {}) }

So now it can be used like this:

{ 
    ...['a', 'b', 'c', 'd'].ditto(1),
    ...['e', 'f'].ditto(2)
    geh: function() { alert("Hi!") }
}

Explanation: the .reduce starts off with an empty object {} and for each element prop return an object which is whatever was in the object already ...obj plus a new property with our value 1: [prop]: 1. Then expand these properties into the outer object with the ... at the start.

If you had tons of properties reduce wouldn't be the most efficient, but you could change it to:

Array.prototype.ditto = function(v) { let o = {}; this.forEach(p => o[p] = v); return o; }

More readable and more efficient but less cool??

John Leonard
  • 909
  • 11
  • 18