通过使用Object.create(null)
而不是从Object.prototype
继承,您的对象不再具有对象原型上的方法。那么显而易见的问题是,该原型上有哪些方法,您是否需要它们?
这些方法包括:
hasOwnProperty
isPrototypeOf
propertyIsEnumerable
toString
/toLocaleString
valueOf
hasOwnProperty
似乎有点无用,因为如果没有原型,创建的对象上的所有属性都是自己的属性。但是,某些库或其他代码可能正在使用for...in
遍历对象的属性,并使用if (o.hasOwnProperty(key))
惯用语。现在这样的代码将失败。或者,您可能正在创建一个子对象,并将创建的对象作为原型,想知道一个属性是子对象的自有属性还是来自原型。
isPrototypeOf
可能有用,如果您计划将创建的对象用作其他对象的原型,并且由于某种原因想要检查创建的对象是否在这些其他对象的原型链中。
propertyIsEnumerable
不会被过多使用,但我们无法预测系统中的其他代码会做什么。如果它尝试在创建的对象上调用此方法,或者任何以它作为原型创建的对象,则会失败。
toString
同样如此。谁知道谁可能会尝试在您创建的对象上调用它?例如,一些库可能会尝试通过执行 toString
并查看结果是否为 "[object Object]"
来测试值的类型。希望他们进行安全的 Object.prototype.toString.call(o)
,但是......
valueOf
很少被显式使用,但如果引擎需要将对象强制转换为原始值,则会调用它。如果缺少它,代码可能会出错:
> o2 = Object.create(null)
> o2 + 1
Uncaught TypeError: Cannot convert object to primitive value
当然,也有可能有人向
Object
原型添加了方法,在这种情况下,
Object.create({})
将会捕获它们。也许你不想要或不需要它们。另一方面,它们很可能是无害的。
考虑到所有这些,似乎应该将
Object.create(null)
限制在特定情况下,可以证明上述问题都不会发生。例如,对象从未传递到其本地上下文之外,或永远不会用作另一个对象的原型。即使在这种情况下,性能优势也非常小,甚至为零。
我想知道其他人是否使用Object.create(null)
?在JavaScript领域中,这是标准操作吗?
我认为它不能被称为标准操作。
Object.keys(...).forEach(...)
和其他可以直接应用于自身属性数组的Array方法。另一方面,也可以使用if (o.hasOwnProperty(s)
而不是if (s in o)
。我想这归结于看待特定情况,因为将一个具有null
的[[Prototype]]
对象视为普通对象可能会导致奇怪的结果(例如没有valueOf、toString或constructor属性)。var o = Object.create(null);console.log(o+'')
会抛出错误。 - RobGObject.prototype.hasOwnProperty.call(obj, prop)
。;-) 我理解OP的观点,即对象只会像if (prop in obj)
这样使用,在这种情况下是有意义的。 - RobG