89

The question I have is best given by way of this jsfiddle, the code for which is below:

var a = 1, b = 'x', c = true;

var d = {a: a, b: b, c: c}; // <--- object literal
var e = [a, b, c];          // <--- array
var f = {a, b, c};          // <--- what exactly is this??

// these all give the same output:
alert(d.a  + ', ' + d.b +  ', ' + d.c );
alert(e[0] + ', ' + e[1] + ', ' + e[2]);
alert(f.a  + ', ' + f.b +  ', ' + f.c );

What sort of a data structure is f? Is it just a shorthand for d?

drmrbrewer
  • 8,355
  • 11
  • 60
  • 138
  • 25
    The first one actually is not JSON. – GolezTrol Dec 22 '15 at 11:24
  • 8
    [That's not the only shorthand, there are a few more in ES6](https://github.com/lukehoban/es6features#enhanced-object-literals) – Kos Dec 22 '15 at 11:24
  • 1
    OK @GolezTrol it's not strictly JSON because the keys aren't in double quotes. So what exactly *would* you call the `d` data structure in my post? – drmrbrewer Dec 22 '15 at 11:34
  • 6
    It's important to understand that none of the versions are valid JSON. The way to represent the data as a JSON string would be `{"a" : 1, "b" : "x", "c" : true }` – Benjamin Gruenbaum Dec 22 '15 at 12:38
  • 14
    @drmrbrewer It is an [object literal](https://developer.mozilla.org/it/docs/Web/JavaScript/Guide/Grammar_and_Types#Object_literals). it is not JSON because it is _javascript code_, whilst JSON is a serialisation format. For instance `var a = '{ "a" : "value"}'` -> `a` holds a string that can be deserialised to an object via `JSON.parse`. – moonwave99 Dec 22 '15 at 12:52
  • OK I've edited my post, thanks. – drmrbrewer Dec 22 '15 at 14:20

3 Answers3

77
var f = {a, b, c};

It came with ES6 (ECMAScript 2015) and means exactly the same as:

var f = {a: a, b: b, c: c};

It is called Object Literal Property Value Shorthands (or simply property value shorthand, shorthand properties).

You can also combine shorthands with classical initialization:

var f = {a: 1, b, c};

For more information see Object initializer.

madox2
  • 39,489
  • 13
  • 88
  • 91
72

It is an Object Initializer Property Shorthand in ES6.

var f = {a, b, c, d:1}; // Will be equal to {a:a, b:b, c:c, d:1}

This works because the property value has the same name as the property identifier. This a new addition to the syntax of Object Initialiser (section 11.1.5) in the latest ECMAScript 6 draft Rev 13. And of course, just like the limitations set from ECMAScript 3, you can’t use a reserved word as your property name.

Such a shorthand won’t dramatically change your code, it only makes everything a little bit sweeter!

function createCar(name, brand, speed) {
  return { type: 'Car', name: name, brand: brand, speed: speed };
}

// With the new shorthand form
function createSweetCar(name, brand, speed) {
  return { type: 'Car', name, brand, speed }; // Yes it looks sweet.
}

Please see the compatibility table for support for these notations. In non-supporting environments, these notations will lead to syntax errors.

This shorthand notation offers object matching pretty nicely:

In ECMAScript5 what we used to do:

var tmp = getData();
var op  = tmp.op;
var lhs = tmp.lhs;
var rhs = tmp.rhs;

Can be done in ECMAScript6 with a single line of code:

var { op, lhs, rhs } = getData();
Scaramouche
  • 2,950
  • 1
  • 16
  • 42
void
  • 33,471
  • 8
  • 45
  • 91
  • 10
    Why would this be so useful as to become a language feature? It seems like it would be much more common for people to either initialize the object directly with literals, return values, and such, or to just create the object first, then set the properties directly. Creating variables with the same names, instantiating them, and then finally initializing the object like this just seems unusual...or does it? – Panzercrisis Dec 22 '15 at 15:27
  • 3
    @Panzercrisis It seems like it would just lead to a lot of unintended and hard to find bugs, personally. Much the same way that allowing `if(a = 1) {...}` as valid syntax does. – Anthony Grist Dec 22 '15 at 16:27
  • where do the values for `brand` and `speed` come from in the second function? – ferry Dec 22 '15 at 18:37
  • @ferry they are passed as the param, was a typo earlier, edited. – void Dec 22 '15 at 18:38
  • @Panzercrisis It's common in the revealing module pattern. – Paul Dec 22 '15 at 19:20
  • 1
    @Panzercrisis I think it at least makes sense if you imagine that a, b, and c as more complex data structures and f also containing other complex properties. Still not sure it's a great idea, but I could see that being useful. – Josh Rumbut Dec 22 '15 at 23:10
  • 1
    @Panzercrisis it can be very useful to return a tuple from a lambda function, something like `(a, b) => {a, b}`. That's at least how I used the same feature in `C#`. – Vincent van der Weele Dec 23 '15 at 06:00
  • I agree with Panzercrisis, this seems like a quite unmotivated and unnecessary addition to the language. I think it looks strange, not sweet, and I'm afraid that a language full of quirks like these just makes it more complex and confusing. – Alex Jan 05 '16 at 10:49
  • 2
    @Alex how is this a "quirk" or "complex"? A very common thing you'd normally find in many codebases is initialising an object where the key matches the variable given as value `{id: id, data: data, isSelected: isSelected}` etc. Happens a lot when mapping objects coming in to local ones and then back. In the majority of cases you don't want to name your stuff slightly differently `{identifier: id, viewData: data, isElementSelected: isSelected }` is exactly that "quirky", "complex" and "confusing" you are talking about. – VLAZ Feb 22 '19 at 12:29
  • @VLAZ You can call your last example for overly verbose, I give you that, but certainly not quirky or complex. It should be perfectly clear with anyone with the most basic understanding of the language what that does. There are isolated use-cases for everything, but I believe that good design in general should provide a simple interface and avoid to clutter the product with a long tail of rarely used functionality that's not really needed. Even when we are talking about the design of a programming language. It's more intuitive, keeps code look uniform across the universe, less to learn. – Alex Feb 22 '19 at 13:06
  • 1
    @Alex removing `id: id` *is* removing clutter and providing a simple interface. Especially if you are providing mapping of something that's very long , like `roleAdministrationRightSelectionDisplayItem` - that's a real field I current work with. It's not in JS but still - if the payload I currently send/receive in Java was sent to a browser, you'd get that key. And if I wanted to do `{ roleAdministrationRightSelectionDisplayItem: roleAdministrationRightSelectionDisplayItem }` in an object literal, *that's* clutter. Don't like it or need it? Don't use it. It helps the rest of us. – VLAZ Feb 22 '19 at 13:22
  • @VLAZ I'm referring to the interface of the language, additions of more features is per definition increasing the complexity of the language. You can reduce the complexity of the source code by relying on the existence of _another_ abstraction in your mind that maps to an _additional_ interface of the language. We are only moving complexity around between different domains. It might simplify writing code, but requires a deeper cognitive model of the language constructs. It wouldn't be relevant if code is strictly personal and we all can use the language constructs that we know and like… – Alex Feb 22 '19 at 15:53
  • …, but since code for us programmers in reality is a globally shared artifact, it requires everyone to keep up with everything for the ecosystem to be efficient. I'm not putting this all on this particular language feature, that would be silly, I just want to point out that the addition of features to a language is not free. I wouldn't want to work in a language where you can do things in a thousand different ways each optimized for a particular narrow use case. I'd rather have a simpler language that has a coherent interface. – Alex Feb 22 '19 at 15:54
12
var f = {a, b, c};          // <--- what exactly is this??

It defines an object in JavaScript using the new ECMAScript 2015 notation:

As per Mozilla Developer Network:

"Objects can be initialized using new Object(), Object.create(), or using the literal notation (initializer notation). An object initializer is a list of zero or more pairs of property names and associated values of an object, enclosed in curly braces ({})."

var a = "foo", 
    b = 42, 
    c = {};

// Shorthand property names (ES6)
var o = { a, b, c }; 

is equivalent to:

var a = "foo", 
    b = 42,
    c = {};

var o = { 
  a: a,
  b: b,
  c: c
};
MojoJojo
  • 2,936
  • 2
  • 20
  • 46