如何从一个没有原型的对象创建一个有默认原型的JS对象?

How to create a JS object with the default prototype from an object without a prototype?

背景: 例如,模块 query-string 能够将 key=value&hello=universe 解析为对象 {key: 'value', hello: 'universe'}。但是,模块作者已决定返回的对象没有原型。也就是说,这个“混蛋”对象是由Object.create(null).

创建的

问题:使用parsed.hasOwnProperty('hello')会很方便,但如果没有默认的对象原型是不可能的。当然,可以Object.prototype.hasOwnProperty.call(parsed, 'hello'),但我想我们都同意这样的表达方式是 kill-immediately-after-birth 丑陋的。

问题:如何将无原型的对象漂亮的转换为具有默认的对象原型和方法,如hasOwnProperty?此外,是否可以在不使用 the feared __proto__setPrototypeOf 的情况下完成?

我不能说我以前做过这个,但这是一种方法

let bastard = Object.create(null);
bastard.father = 'vader';

let adopted = Object.assign({}, bastard);
console.log(adopted.hasOwnProperty('father')); // => true

setPrototypeOf()没有什么可怕的,但是没有它你可能会这样做;

var o1 = Object.create(null),
    o2;
o1.test = "42";
o2 = Object.assign({},o1);
console.log(o2.test);
console.log(o2.constructor.prototype);

It would be convenient to use parsed.hasOwnProperty('hello') but that is not possible without the default object prototype

创建这样一个 "bastard object" 的全部意义在于你不能这样做 - 如果有人向你的服务器发送了一个查询字符串 ?hasOwnProperty=oops 怎么办?

How to nicely convert the prototypeless object to have a default object prototype and methods such as hasOwnProperty?

不要。 您应该使用带 call 的长格式,或者直接使用 in operator,它完全符合您的需要:

'hello' in parsed

在 ES6 环境中,您可能还想将对象转换为适当的 Map 并使用它 has 方法。

我不建议更改第三方包的原型,它可能会被冻结并容易出现运行时错误。我会按照@Bergi 的建议使用内置的 in 运算符,或者使用 ES6 Reflect API.

const _ = console.info

const parsed = (
  { __proto__: null
  , foo: 'fu'
  , bar: 'bra'
  }
)

_('foo' in parsed) // true

_('fu' in parsed) // false


/** ES6 (fully supported in current browsers) */

_(Reflect.has(parsed, 'foo')) // true

_(Reflect.has(parsed, 'fu')) // false