22
I’m going through a technical doubt in Javascript:
- What’s the difference between
Object.create
andnew Object()
? - What cases do I have to adopt one over the other?
22
I’m going through a technical doubt in Javascript:
Object.create
and new Object()
?6
The method Object.create
receive parameters. The first is required and will be used as prototype of the new object. The second is a map of properties with which object is already "born".
Already new Object()
is a longer and not recommended way of saying {}
.
The three lines of code below are equivalent:
let a = {}; // legal
let b = new Object(); // coisa de dinossauros pedantes
let c = Object.create(null); // isso pode ser útil se ao invés de nulo
//você passar um parâmetro.
The method create
can be quite useful if you use some more complex logic to create your objects. Again, the two snippets of code below are equivalent:
// forma verbosa
let foo = {};
foo.prototype = Array;
let bar = {nome: "john", idade: 21};
for (let propriedade in bar) {
foo[propriedade] = bar[propriedade];
}
// forma curta
let foo = Object.create(Array, {nome: "john", idade: 21});
6
In the great majority sometimes, to create an object in Javascript, just do something like this:
const myObject = {
// ...
};
So, a new object will have been created myObject
whose prototype points to Object.prototype
. The {}
(literal form), is analogous to use new Object()
or Object()
. Despite this equivalence, always use {}
.
Already the function Object.create
, differently demonstrated above, shall be used when:
Therefore, when creating an object with {}
, new Object()
or Object()
, is limited to a new object whose prototype is always Object.prototype
. The function Object.create
allows the creation of objects with a different prototype and/or properties with defined descriptors with higher granularity.
Object.create
The first argument of Object.create
is useful to define a "custom prototype" in the creation of an object. So, in the example below:
const customPrototype = {}; // Qualquer objeto.
const obj = Object.create(customPrototype);
The object obj
will prototype the object customPrototype
, which was passed in the first argument of the function. Then the evaluation of Reflect.getPrototypeOf(obj) === customPrototype
would result in true.
It’s kind of the same as this:
const customPrototype = {}; // Qualquer objeto.
const obj = {};
Reflect.setPrototypeOf(obj, customPrototype);
The disadvantage of redefining the prototype after the object has been created is that the actuasi Javascript interpreters do not have optimizations for the prototypical reset, since it is an unusual and relatively costly operation (the entire prototyping chain of the object will be changed). Therefore, it is more appropriate to define the customized prototype during the creating of the object than to do this once the object has already been created. Therefore there is the first argument of Object.create
.
Object.create
The second argument from Object.create
defines the property descriptors that the object to be created will possess.
Contrary to the many people think, the second argument of Object.create
does not serve to define initial properties for an object, but rather to define the property descriptors initials that the object will take over. About property descriptors and attributes, it is an extensive subject that gives an answer by itself. I deal in more detail about them in What and how Javascript property descriptors and attributes work?.
So an example (creating a new object whose prototype is null
and with the property descriptors):
const obj = Object.create(null, {
name: {
value: 'Bob',
writable: false,
enumerable: false,
configurable: false
},
age: {
value: 50,
writable: false,
enumerable: false,
configurable: false
}
});
console.log(obj);
console.log(Object.keys(obj));
console.log('---\nAs propriedades estão aqui!');
// As propriedades estão lá! Só não podem ser enumeradas
// normalmente porque o atributo `enumerable` de cada
// propriedade foi definido, na criação, como `false`.
console.log(Object.getOwnPropertyNames(obj));
console.log(obj.name);
console.log(obj.age);
So it’s not right to do this:
// Este código não é válido.
const obj = Object.create(null, {
name: 'Bob',
age: 50
});
As the second argument does not contain descriptor(s) of property valid(s), the following error will be launched:
Uncaught TypeError: Property description must be an object
It is less intuitive and less useful. It would be much more interesting to use the second argument of Object.create
to define the estates (not to be confused with property descriptor) to be assumed by the object during its creation. If necessary, one can combine Object.create
with Object.assign
:
// Criaremos um objeto cujo protótipo é `null`
// E as propriedades definidas inicialmente são `name` e `age`:
const obj = Object.assign(Object.create(null), {
name: 'Bob',
age: 50
});
console.log(obj); //=> { name: "Bob", age: 50 }
console.log(Reflect.getPrototypeOf(obj)); //=> null
More details about the Object.assign
in this answer or in the documentation.
As a matter of curiosity, in addition to Object.create
, the functions Object.defineProperty
and Object.defineProperties
can also be used to define properties by describing properties on an object. The difference is that Object.create
makes in creation and, the last two, once the object has been created.
{}
, Object()
and new Object()
Are equivalent:
1 | const a = {};
2 | const b = new Object();
3 | const c = Object();
In line 1, an object is created from the literal notation. In line 2, an object is created from the instantiation of the constructor Object
. In line 3, an object is created from the invocation of Object
. All three will create a new object whose prototype is Object.prototype
.
Demonstration:
const a = {};
const b = new Object();
const c = Object();
console.log(Reflect.getPrototypeOf(a) === Object.prototype); //=> true
console.log(Reflect.getPrototypeOf(b) === Object.prototype); //=> true
console.log(Reflect.getPrototypeOf(c) === Object.prototype); //=> true
So, nay it is correct to say that the above three forms are equivalent to Object.create(null)
, since the prototypes are different.
When using Object.create(null)
, creates a new object in which null
is the prototype. Already use {}
, Object()
or new Object()
are three forms equivalents to create a new object in which Object.prototype
is the prototype.
However, Object.create(Object.prototype)
is, yes, equivalent to the three forms in question.
They are subtle details, but they make a difference. This another excellent answer gives more details on the prototyping chain, which is a fundamental concept to understand this answer about Object.create
.
In addition, the reading on property descriptors is also important to fully understand the functioning of Object.create
.
Browser other questions tagged javascript characteristic-language objects
You are not signed in. Login or sign up in order to post.
Wow, I use new Object().... I felt offended :p.
– Edgar Muniz Berlinck
Pedant dinosaur coia was great.
foo.prototype = Array
You have no right to appeal, you go straight to the gallows. I don’t have time to elaborate a response, but there are some particularities of each method, for example, withObject.create
you can "inherit" the properties of an object without inheriting its prototype, as well as do a number of interesting things (e. g.,mixin
). For more details: MDN - Object.create().– Anthony Accioly
Another interesting reference: Adobe Developer Connection - Javascript Object Creation: Learning to live without "new"
– Anthony Accioly
Hi! Your answer is with several incorrect and/or inaccurate details. I will highlight them here: 1) The second argument of
Object.assign
nay serves to "define the properties with which object is already born", but rather defines the property descriptors initials. 2)Object.assign(null)
is not the same as{}
ornew Object
(as the first example of code incorrectly suggests). 3) The second example of code is incorrect, since the propertyprototype
nay defines a prototype, but it is a special property of builders that will be assigned to the prototype [...]– Luiz Felipe
object during instantiation. Use the (not recommended) property
__proto__
for that or methods such asReflect.setPrototypeOf
orObject.setPrototypeOf
to do so. Furthermore, as I said earlier, the second argument ofObject.assign
does not define initial properties, but rather initial property descriptors, so that makes this incorrect:Object.create(Array, {nome: "john", idade: 21})
. I tried to detail a little more in the reply I wrote.– Luiz Felipe