Object
A few additional static helpers have been added to Object
. Traditionally, functions of this sort have been seen as focused on the behaviors/capabilities of object values.
However, starting with ES6, Object
static functions will also be for general-purpose global APIs of any sort that don’t already belong more naturally in some other location (i.e., Array.from(..)
).
Object.is(..)
Static Function
The Object.is(..)
static function makes value comparisons in an even more strict fashion than the ===
comparison.
Object.is(..)
invokes the underlying SameValue
algorithm (ES6 spec, section 7.2.9). The SameValue
algorithm is basically the same as the ===
Strict Equality Comparison Algorithm (ES6 spec, section 7.2.13), with two important exceptions.
Consider:
var x = NaN, y = 0, z = -0;
x === x; // false
y === z; // true
Object.is( x, x ); // true
Object.is( y, z ); // false
You should continue to use ===
for strict equality comparisons; Object.is(..)
shouldn’t be thought of as a replacement for the operator. However, in cases where you’re trying to strictly identify a NaN
or -0
value, Object.is(..)
is now the preferred option.
Note: ES6 also adds a Number.isNaN(..)
utility (discussed later in this chapter) which may be a slightly more convenient test; you may prefer Number.isNaN(x)
over Object.is(x,NaN)
. You can accurately test for -0
with a clumsy x == 0 && 1 / x === -Infinity
, but in this case Object.is(x,-0)
is much better.
Object.getOwnPropertySymbols(..)
Static Function
The “Symbols” section in Chapter 2 discusses the new Symbol primitive value type in ES6.
Symbols are likely going to be mostly used as special (meta) properties on objects. So the Object.getOwnPropertySymbols(..)
utility was introduced, which retrieves only the symbol properties directly on an object:
var o = {
foo: 42,
[ Symbol( "bar" ) ]: "hello world",
baz: true
};
Object.getOwnPropertySymbols( o ); // [ Symbol(bar) ]
Object.setPrototypeOf(..)
Static Function
Also in Chapter 2, we mentioned the Object.setPrototypeOf(..)
utility, which (unsurprisingly) sets the [[Prototype]]
of an object for the purposes of behavior delegation (see the this & Object Prototypes title of this series). Consider:
var o1 = {
foo() { console.log( "foo" ); }
};
var o2 = {
// .. o2's definition ..
};
Object.setPrototypeOf( o2, o1 );
// delegates to `o1.foo()`
o2.foo(); // foo
Alternatively:
var o1 = {
foo() { console.log( "foo" ); }
};
var o2 = Object.setPrototypeOf( {
// .. o2's definition ..
}, o1 );
// delegates to `o1.foo()`
o2.foo(); // foo
In both previous snippets, the relationship between o2
and o1
appears at the end of the o2
definition. More commonly, the relationship between an o2
and o1
is specified at the top of the o2
definition, as it is with classes, and also with __proto__
in object literals (see “Setting [[Prototype]]
“ in Chapter 2).
Warning: Setting a [[Prototype]]
right after object creation is reasonable, as shown. But changing it much later is generally not a good idea and will usually lead to more confusion than clarity.
Object.assign(..)
Static Function
Many JavaScript libraries/frameworks provide utilities for copying/mixing one object’s properties into another (e.g., jQuery’s extend(..)
). There are various nuanced differences between these different utilities, such as whether a property with value undefined
is ignored or not.
ES6 adds Object.assign(..)
, which is a simplified version of these algorithms. The first argument is the target, and any other arguments passed are the sources, which will be processed in listed order. For each source, its enumerable and own (e.g., not “inherited”) keys, including symbols, are copied as if by plain =
assignment. Object.assign(..)
returns the target object.
Consider this object setup:
var target = {},
o1 = { a: 1 }, o2 = { b: 2 },
o3 = { c: 3 }, o4 = { d: 4 };
// setup read-only property
Object.defineProperty( o3, "e", {
value: 5,
enumerable: true,
writable: false,
configurable: false
} );
// setup non-enumerable property
Object.defineProperty( o3, "f", {
value: 6,
enumerable: false
} );
o3[ Symbol( "g" ) ] = 7;
// setup non-enumerable symbol
Object.defineProperty( o3, Symbol( "h" ), {
value: 8,
enumerable: false
} );
Object.setPrototypeOf( o3, o4 );
Only the properties a
, b
, c
, e
, and Symbol("g")
will be copied to target
:
Object.assign( target, o1, o2, o3 );
target.a; // 1
target.b; // 2
target.c; // 3
Object.getOwnPropertyDescriptor( target, "e" );
// { value: 5, writable: true, enumerable: true,
// configurable: true }
Object.getOwnPropertySymbols( target );
// [Symbol("g")]
The d
, f
, and Symbol("h")
properties are omitted from copying; non-enumerable properties and non-owned properties are all excluded from the assignment. Also, e
is copied as a normal property assignment, not duplicated as a read-only property.
In an earlier section, we showed using setPrototypeOf(..)
to set up a [[Prototype]]
relationship between an o2
and o1
object. There’s another form that leverages Object.assign(..)
:
var o1 = {
foo() { console.log( "foo" ); }
};
var o2 = Object.assign(
Object.create( o1 ),
{
// .. o2's definition ..
}
);
// delegates to `o1.foo()`
o2.foo(); // foo
Note: Object.create(..)
is the ES5 standard utility that creates an empty object that is [[Prototype]]
-linked. See the this & Object Prototypes title of this series for more information.