Object.create
可以用提供的对象做新对象的 __proto__
。这导致了一个很有趣的现象,如果使用 Object.create(null)
来创建新对象,那么这个新对象上就没有任何 __proto__
。因为 JavaScript 的对象经常被用来做字典使用,Object.create(null)
可以让这个功能使用更加的纯粹。
const dict = Object.create(null);
console.log(Object.getPrototypeOf(dict));
// output: null
console.log(typeof dict.hasOwnProperty);
// output: "undefined"
const obj = { };
console.log(Object.getPrototypeOf(obj));
// output:
// {
// constructor,
// hasOwnProperty,
// isPrototypeOf,
// propertyIsEnumerable,
// toLocaleString,
// toString,
// valueOf,
// ...
// }
同样,因为没有 prototype
,理论上来说,后续如果有人对 Object.prototype
做操作,也不会影响到使用。
const dict = Object.create(null);
// ...
Object.prototype.addSomething = () => { };
console.log(typeof dict.addSomething);
// output: undefined
for (const key in dict) console.log(key);
// no output
console.log(typeof ({}).addSomething);
// output: function
for (const key in {}) console.log(key);
// output: 'addSomething'
所以,如果判断对象有某个字段,那么一定是他自身有这个字段,而不会是因为原型链上的定义。也就是说,不需要用:
if (Object.prototype.hasOwnProperty.call(dict, 'addSomething') { }) {
// ...
}
而只需要写:
if (dict.addSomething) {
// ...
}
当然,这也会有一些弊端,比如默认 Object.prototype
的东西就没了,如果需要 toString
之类的函数,得自己写。