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:
{
width: 42, // struct-style unquoted key
'maxWidth': 43, // dict-style quoted key
}
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:
/** @type {{width: number, maxWidth: (number|undefined)}} */
const o = {width: 42};
if (o.hasOwnProperty('maxWidth')) {
...
}
This is best implemented as:
/** @type {{width: number, maxWidth: (number|undefined)}} */
const o = {width: 42};
if (o.maxWidth != null) {
...
}
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:
return {
stuff: 'candy',
method() {
return this.stuff; // Returns 'candy'
},
};
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:
class {
getObjectLiteral() {
this.stuff = 'fruit';
return {
stuff: 'candy',
method: () => this.stuff, // Returns 'fruit'
};
}
}
5.3.6 Shorthand properties
Shorthand properties are allowed on object literals.
Example:
const foo = 1;
const bar = 2;
const obj = {
foo,
bar,
method() { return this.foo + this.bar; },
};
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:
/**
* @param {string} ordinary
* @param {{num: (number|undefined), str: (string|undefined)}=} param1
* num: The number of times to do something.
* str: A string to do stuff to.
*/
function destructured(ordinary, {num, str = 'some default'} = {})
Disallowed:
/** @param {{x: {num: (number|undefined), str: (string|undefined)}}} param1 */
function nestedTooDeeply({x: {num, str}}) {};
/** @param {{num: (number|undefined), str: (string|undefined)}=} param1 */
function nonShorthandProperty({num: a, str: b} = {}) {};
/** @param {{a: number, b: number}} param1 */
function computedKey({a, b, [a + b]: c}) {};
/** @param {{a: number, b: string}=} param1 */
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.
/**
* Supported temperature scales.
* @enum {string}
*/
const TemperatureScale = {
CELSIUS: 'celsius',
FAHRENHEIT: 'fahrenheit',
};
/**
* An enum with two options.
* @enum {number}
*/
const Option = {
/** The option used shall have been the first. */
FIRST_OPTION: 1,
/** The second among two options. */
SECOND_OPTION: 2,
};