5.3 Object literals

5.3.1 Use trailing commas

Include a trailing comma whenever there is a line break between the finalproperty and the closing brace.

5.3.2 Do not use the Object constructor

While Object does not have the same problems as Array, it is stilldisallowed for consistency. Use an object literal ({} or {a: 0, b: 1, c: 2})instead.

5.3.3 Do not mix quoted and unquoted keys

Object literals may represent either structs (with unquoted keys and/orsymbols) or dicts (with quoted and/or computed keys). Do not mix these keytypes in a single object literal.

Disallowed:

  1. {
  2. width: 42, // struct-style unquoted key
  3. 'maxWidth': 43, // dict-style quoted key
  4. }

This also extends to passing the property name to functions, likehasOwnProperty. In particular, doing so will break in compiled code becausethe compiler cannot rename/obfuscate the string literal.

Disallowed:

  1. /** @type {{width: number, maxWidth: (number|undefined)}} */
  2. const o = {width: 42};
  3. if (o.hasOwnProperty('maxWidth')) {
  4. ...
  5. }

This is best implemented as:

  1. /** @type {{width: number, maxWidth: (number|undefined)}} */
  2. const o = {width: 42};
  3. if (o.maxWidth != null) {
  4. ...
  5. }

5.3.4 Computed property names

Computed property names (e.g., {['key' + foo()]: 42}) are allowed, and areconsidered dict-style (quoted) keys (i.e., must not be mixed with non-quotedkeys) unless the computed property is asymbol(e.g., [Symbol.iterator]). Enum values may also be used for computed keys, butshould not be mixed with non-enum keys in the same literal.

5.3.5 Method shorthand

Methods can be defined on object literals using the method shorthand ({method(){… }}) in place of a colon immediately followed by a function or arrowfunction literal.

Example:

  1. return {
  2. stuff: 'candy',
  3. method() {
  4. return this.stuff; // Returns 'candy'
  5. },
  6. };

Note that this in a method shorthand or function refers to the objectliteral itself whereas this in an arrow function refers to the scope outsidethe object literal.

Example:

  1. class {
  2. getObjectLiteral() {
  3. this.stuff = 'fruit';
  4. return {
  5. stuff: 'candy',
  6. method: () => this.stuff, // Returns 'fruit'
  7. };
  8. }
  9. }

5.3.6 Shorthand properties

Shorthand properties are allowed on object literals.

Example:

  1. const foo = 1;
  2. const bar = 2;
  3. const obj = {
  4. foo,
  5. bar,
  6. method() { return this.foo + this.bar; },
  7. };
  8. assertEquals(3, obj.method());

5.3.7 Destructuring

Object destructuring patterns may be used on the left-hand side of an assignmentto perform destructuring and unpack multiple values from a single object.

Destructured objects may also be used as function parameters, but should be keptas simple as possible: a single level of unquoted shorthand properties. Deeperlevels of nesting and computed properties may not be used in parameterdestructuring. Specify any default values in the left-hand-side of thedestructured parameter ({str = 'some default'} = {}, rather than {str} = {str: 'some default'}), and if a destructuredobject is itself optional, it must default to {}. The JSDoc for thedestructured parameter may be given any name (the name is unused but is requiredby the compiler).

Example:

  1. /**
  2. * @param {string} ordinary
  3. * @param {{num: (number|undefined), str: (string|undefined)}=} param1
  4. * num: The number of times to do something.
  5. * str: A string to do stuff to.
  6. */
  7. function destructured(ordinary, {num, str = 'some default'} = {})

Disallowed:

  1. /** @param {{x: {num: (number|undefined), str: (string|undefined)}}} param1 */
  2. function nestedTooDeeply({x: {num, str}}) {};
  3. /** @param {{num: (number|undefined), str: (string|undefined)}=} param1 */
  4. function nonShorthandProperty({num: a, str: b} = {}) {};
  5. /** @param {{a: number, b: number}} param1 */
  6. function computedKey({a, b, [a + b]: c}) {};
  7. /** @param {{a: number, b: string}=} param1 */
  8. function nontrivialDefault({a, b} = {a: 2, b: 4}) {};

Destructuring may also be used for goog.require statements, and in this casemust not be wrapped: the entire statement occupies one line, regardless of howlong it is (see ??).

5.3.8 Enums

Enumerations are defined by adding the @enum annotation to an object literal.Additional properties may not be added to an enum after it is defined. Enumsmust be constant, and all enum values must be deeply immutable.

  1. /**
  2. * Supported temperature scales.
  3. * @enum {string}
  4. */
  5. const TemperatureScale = {
  6. CELSIUS: 'celsius',
  7. FAHRENHEIT: 'fahrenheit',
  8. };
  9. /**
  10. * An enum with two options.
  11. * @enum {number}
  12. */
  13. const Option = {
  14. /** The option used shall have been the first. */
  15. FIRST_OPTION: 1,
  16. /** The second among two options. */
  17. SECOND_OPTION: 2,
  18. };