• Object.create(proto, [descriptors]) : 利用给定的 proto 作为 [[Prototype]] 和可选的属性描述来创建一个空对象
    1. obj = {
    2. '__proto__':"value"
    3. }
    4. console.log(obj) // {} [__proto__]被忽略
    __proto__ 属性很特别:它必须是对象或者 null。字符串不能成为 prototype。
    因此,如果 obj.__proto__ 被读取或者赋值,那么对应的 getter/setter 会被从它的原型中调用,它会 set/get [[Prototype]]

Object.create(null)

  1. let obj = Object.create(null)
  2. obj['__proto__'] = "value"
  3. console.log(obj) // {__proto__: "value"}
  4. alert(obj) // Error (no toString)

Object.create(null) 创建了一个空对象,这个对象是没有原型([[Prototype]]null)的 very plain
因此,它没有继承 **__proto__** 的 getter/setter 方法。

  1. let obj = Object.create(null);
  2. obj.__proto__ = Array.prototype;
  3. console.log(obj.__proto__); // [constructor: ƒ, concat: ƒ,…]
  4. console.log(obj.slice); // undefined
  5. console.log(obj.__proto__.slice); // ƒ slice() { [native code] }

第2行代码中,设置的proto只是一个普通的属性,没有改变[[Prototype]]。
因为,通过obj.``__proto__``= xxx设置obj的原型对象,需要调用Object.prototypeset __proto__()属性,但因为obj.__proto__= null,所以无法获取到该属性。
正确做法:
Object.setPrototypeOf(obj, Array.prototype)

可以使用 Object.create 来实现比复制 for..in 循环中的属性更强大的对象克隆方式:

  1. let clone = Object.create(Object.getPrototypeOf(obj), Object.getOwnPropertyDescriptors(obj));

此调用可以对 obj 进行真正准确地拷贝,包括所有的属性:可枚举和不可枚举的,数据属性和 setters/getters —— 包括所有内容,并带有正确的 [[Prototype]]

手写Object.create()