Shallow Clone (excluding prototype)
let aClone = { ...a };
Desugars into:
let aClone = Object.assign({}, a);
Merging Two Objects
let ab = { ...a, ...b };
Desugars into:
let ab = Object.assign({}, a, b);
Overriding Properties
let aWithOverrides = { ...a, x: 1, y: 2 };
// equivalent to
let aWithOverrides = { ...a, ...{ x: 1, y: 2 } };
// equivalent to
let x = 1, y = 2, aWithOverrides = { ...a, x, y };
Desugars into:
let aWithOverrides = Object.assign({}, a, { x: 1, y: 2 });
Default Properties
let aWithDefaults = { x: 1, y: 2, ...a };
Desugars into:
let aWithDefaults = Object.assign({}, { x: 1, y: 2 }, a);
// which can be optimized without the empty object
let aWithDefaults = Object.assign({ x: 1, y: 2 }, a);
Multiple Merges
// getters on a are executed twice
let xyWithAandB = { x: 1, ...a, y: 2, ...b, ...a };
Desugars into:
let xyWithAandB = Object.assign({ x: 1 }, a, { y: 2 }, b, a);
Getters on the Object Initializer
// Does not throw because .x isn't evaluated yet. It's defined.
let aWithXGetter = { ...a, get x() { throw new Error('not thrown yet') } };
Desugars into:
let aWithXGetter = {};
Object.assign(aWithXGetter, a);
Object.defineProperty(aWithXGetter, "x", {
get(){ throw new Error('not thrown yet') },
enumerable : true,
configurable : true
});
Getters in the Spread Object
// Throws because the .x property of the inner object is evaluated when the
// property value is copied over to the surrounding object initializer.
let runtimeError = { ...a, ...{ get x() { throw new Error('thrown now') } } };
Setters Are Not Executed When They're Redefined
let z = { set x() { throw new Error(); }, ...{ x: 1 } }; // No error
Null/Undefined Are Ignored
let emptyObject = { ...null, ...undefined }; // no runtime error
Updating Deep Immutable Object
let newVersion = {
...previousVersion,
name: 'New Name', // Override the name property
address: { ...previousVersion.address, zipCode: '99999' } // Update nested zip code
items: [...previousVersion.items, { title: 'New Item' }] // Add an item to the list of items
};
Successor-ML
{ ... = a, x = 1, y = 2 }
http://successor-ml.org/index.php?title=Functional_record_extension_and_row_capture
Elm
{ a | x <- 1, y <- 2 }
http://elm-lang.org/learn/Records.elm#updating-records
OCaml
{ a with x = 1; y = 2 }
https://realworldocaml.org/v1/en/html/records.html#functional-updates
Haskell
a { x = 1, y = 2 }
http://www.haskell.org/haskellwiki/Default_values_in_records