By not inheriting from Object.prototype
with Object.create(null)
, your object no longer has the methods on the object prototype. So the obvious question is, what are the methods on that prototype, and do you need them?
The methods are:
hasOwnProperty
isPrototypeOf
propertyIsEnumerable
toString
/toLocaleString
valueOf
hasOwnProperty
seems kind of useless because if there is no prototype, all properties on the created object are by definition own properties. However, it's conceivable that some library or other piece of code might be iterating over the object's properties with for...in
and using the if (o.hasOwnProperty(key))
idiom. It is probably too much to hope for that it would use the more correct Object.prototype.hasOwnProperty.call(o, key)
. Such code would now fail. Or, you might be creating a sub-object with the created object as prototype, and be interested in knowing whether a property is an own property of the sub-object or comes from the prototype.
isPrototypeOf
might or might not be useful if you plan to use the created object as the prototype for other objects, and for some reason want to check if the created object is or is not in the prototype chain of such other objects.
propertyIsEnumerable
would not be used too much, but then again, we cannot predict what other code in the system is going to do. If it tries to call this method on the created object, or any objects created with it as a prototype, it will fail.
The same holds for toString
. Who knows who might try to call it on your created object? For instance, some libraries might try to test a value's type by doing a toString
and seeing if the result is "[object Object]"
. Hopefully they do a safe Object.prototype.toString.call(o)
, but...
valueOf
is rarely used explicitly, but is called by the engine if it needs to coerce the object to a primitive. If it is missing, the code could break:
> o2 = Object.create(null)
> o2 + 1
Uncaught TypeError: Cannot convert object to primitive value
Of course, there is also the possibility that someone has added methods to the Object
prototype, in which case Object.create({})
will pick them up. Probably you don't want or need them. On the other hand, they are most likely harmless.
Given all of this, it seems that Object.create(null)
should be limited to specific cases where it is provable that none of the above issues could occur. For instance, where the object is never even passed outside its local context, or is never going to be used as a prototype for another object. Even in that case, the performance advantage will be very small, or even zero.
I'm interested to know if others use
Object.create(null)
? Is it SOP in JavaScript land?
I don't think it could be called SOP.
To the best of my knowledge,
{} == Object.create(Object.prototype);
Also,
To me (Only me) I feel like Object.create(null)
gives you more clarity that your object is not going to inherit anything i.e its (purely) empty map
.
Also,
In both cases you can use object as dictionary.
Also,
It depend upto you what you supposed to do with your object.
When,
{} == Object.create(Object.prototype);
// you inherit all object properties
o = Object.create(null);
// you do not inherit anything. this is completely blank object.
If you are using an object as a map, and you create an object using method 1 above, then you have to be extra careful when doing lookups in the map. Because the properties and methods from Object are inherited, your code may run into a case where there are keys in the map that you never inserted.
For example, if you did a lookup on toString, you would find a function, even though you never put that value there. You can work around that like this:
if (Object.prototype.hasOwnProperty.call(object, 'toString')) {
// we actually inserted a 'toString' key into object
}
Note that you can't just do object.hasOwnProperty('toString') because you may have inserted a key "hasOwnProperty" into object, so we force it to use the implementation in Object.
On the other hand, if you use method 2 above, then you won't have to worry about things from Object appearing in the map.
You can't check for the existence of a property with a simple if like this:
// Unreliable:
if (object[someKey]) {
// ...
}
SO,
To use object as a Map most of the people on planet use
Object.create(null)
// no overhead to worry about inherited properties.
In all other cases you simply use,
var myObject = {}
MDN - Object.create
MSDN - Object.create
From the book You Don't Know JS: this & Object Prototypes:
Object.create(null)
is similar to{}
, but without the delegation toObject.prototype
, so it's "more empty" than just{}
.
Object.create(null)
is a good practice in case that you need a DMZ
(empty object for explicit binding: apply & call
, bind
).
I'd like to refer to the Mozilla doc about Objects and maps compared here to give Map a chance as a better practice nowaday.
Objects
are similar toMaps
in that both let you set keys to values, retrieve those values, delete keys, and detect whether something is stored at a key. Because of this (and because there were no built-in alternatives),Objects
have been used asMaps
historically; however, there are important differences that make using aMap
preferable in certain cases:
- The keys of an
Object
are Strings and Symbols, whereas they can be any value for aMap
, including functions, objects, and any primitive.- You can get the size of a
Map
easily with the size property, while the number of properties in anObject
must be determined manually.- A
Map
is an iterable and can thus be directly iterated, whereas iterating over anObject
requires obtaining its keys in some fashion and iterating over them.- An
Object
has a prototype, so there are default keys in the map that could collide with your keys if you're not careful. As of ES5 this can be bypassed by usingmap = Object.create(null)
, but this is seldom done.- A
Map
may perform better in scenarios involving frequent addition and removal of key pairs.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With