New version of this blog post: inside “
ECMAScript 6: new OOP features besides classes”.
Copying all properties of one object to another one is a common operation in JavaScript. This blog post explains ECMAScript 6’s implementation of it, which is called Object.assign().
This merging operation has a name in the JavaScript ecosystem that is only used there (and, unfortunately, clashes with classic OOP terminology): “extend”. Two examples of “extend” being provided by libraries:
Object.assign()
For merging objects, ECMAScript 6 will have the function
Object.assign(target, source_1, ..., source_n)
This function modifies
target and returns it: it first copies all enumerable
[1] own operties of
source_1 to
target, then those of
source_2, etc.
Property keys: either strings or symbols
In ECMAScript 6, property keys can be either strings or
symbols. The latter are a new kind of unique identifier; there are never any name clashes with symbols as keys.
Object.assign() supports both strings and symbols as keys.
Copying versus assignment
Properties in the target object are created via assignment (internal operation [[Put]]). That means that if
target has (own or inherited) setters
[1], those will be invoked during copying. An alternative would have been to
define new properties
[2], an operation which always creates new own properties and never invokes setters. There originally was a proposal for a variant of
Object.assign() that uses definition instead of assignment. That proposal has been rejected for ECMAScript 6 (but may be reconsidered for later editions).
Use cases for Object.assign()
Setting up instance properties
The task of a constructor is to set up instance properties. Alas, variable names are always mentioned redundantly for this task:
class Point {
constructor(x, y) {
this.x = x;
this.y = y;
}
}
My favorite would have been the following syntax to completely remove that redundancy (CoffeeScript and TypeScript both have ways of doing this, but I prefer this syntax):
class Point {
constructor(this.x, this.y) {
}
}
Object.assign() at least enables you to avoid some of the redundancy:
class Point {
constructor(x, y) {
Object.assign(this, { x, y });
}
}
In ECMAScript 6,
{ x, y } is an abbreviation for
{ x: x, y: y }.
Adding a method to an object
ECMAScript 5, you use a function expression to add a method to an object:
MyClass.prototype.foo = function (arg1, arg2) {
...
};
ECMAScript 6 has a more concise syntax for methods
[3]. Thanks to
Object.assign(), you don’t have to abandon that syntax:
Object.assign(MyClass.prototype, {
foo(arg1, arg2) {
...
}
});
Cloning an object
You can also use
Object.assign() to (shallowly) clone an object:
var copy = Object.assign({ __proto__: obj.__proto__ }, obj);
If you are only interested in an object’s own properties, things become simpler:
var copy = Object.assign({}, obj);
References
- Object properties in JavaScript
- Properties in JavaScript: definition versus assignment
- Callable entities in ECMAScript 6