【问题标题】:How does __proto__ work when object is created with Object.create(null)使用 Object.create(null) 创建对象时 __proto__ 如何工作
【发布时间】:2017-12-17 18:39:18
【问题描述】:

考虑以下 javascript 代码

var a = Object.create(null);
a.foo = 1;
var b = Object.create(a);
console.log(b.foo);  //prints 1
console.log(b.__proto__);  //prints undefined
b.__proto__ = null;
console.log(b.__proto__);  //prints null
console.log(b.foo);  //prints 1

任何人都可以解释对象b 是如何访问a 的“foo”属性,即使在将b.__proto__ 设置为null 之后?访问a属性的内部链接是什么?

我尝试在 SO 中搜索可能的解释,但找不到对 Javascript 的这种特殊行为的任何解释。

【问题讨论】:

    标签: javascript inheritance prototype prototype-chain


    【解决方案1】:

    您的问题是您使用的是deprecated __proto__ property,它是Object.prototype 上的getter/setter - 但您的对象不会从那里继承,所以它最初是undefined,并且分配创建名称为 __proto__ 的标准属性。

    改用正确的Object.getPrototypeOf/Object.setPrototypeOf,代码会如你所愿:

    var a = Object.create(null);
    a.foo = 1;
    var b = Object.create(a);
    console.log(b.foo); // 1
    console.log(Object.getPrototypeOf(b)); // {foo:1} - a
    Object.setPrototypeOf(b, null);
    console.log(Object.getPrototypeOf(b)); // null
    console.log(b.foo); // undefined
    

    【讨论】:

    • 谢谢。你回答了第一个问题。你能解释一下继承在我的代码中是如何工作的吗?它肯定不能通过__proto__ 工作。
    • @Priyanjit 在您的版本中,a 一直是 b 的 [[prototype]]。
    • 这是怎么回事?除了__proto__,还有隐藏的属性吗?因为ab 是两个不同的对象。
    • 当您使用Object.create 时,它就发生了。请注意,__proto__ 不是“隐藏属性”(好吧,它是不可枚举的,但这不是我们的意思)。原型链链接 - 表示为 [[prototype]] - 是一个 internal slot,它是真正“隐藏的”并且不是属性
    • 非常感谢。 @Bergi
    【解决方案2】:

    @Bergi 的回答是正确的。这是__proto__的情况下发生的深入答案

    var a = Object.create({});
    var b = Object.create(a);
    b.__proto__===a; //true
    var c = Object.create(null);
    var d = Object.create(c);
    d.__proto__===c; //false..confusion
    
    Object.hasOwnProperty.call(d,"__proto__"); //false as expected
    Object.hasOwnProperty.call(b,"__proto__"); //false ?
    
    Object.hasOwnProperty.call(Object,"__proto__"); //false
    Object.hasOwnProperty.call(Object.prototype,"__proto__"); //true
    

    这意味着__proto__ 仅存在于Object.prototype

    Object.getOwnPropertyDescriptor(Object.prototype,"__proto__")
    //{enumerable: false, configurable: true, get: ƒ, set: ƒ}
    

    __proto__ 是一个 getter 设置器,它应该返回到对象父对象的内部链接,例如

    get __proto__(){return this.hidden_internal_link_to_parent;}
    

    案例b.__proto__:- b 没有__proto__ 属性,所以它通过[[prototype]] 链到a,然后到a 的父级,最后到Object.prototypeObject.prototype__proto__,它返回b 的父级链接a

    案例d.__proto__:- dObject.prototype 的链接已损坏(d --parent-->c 和 c--parent-->null)。所以d.__proto__ 是未定义的。但是d 有指向c 的内部链接,可以通过Object.getPrototypeOf(d) 访问。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-04-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多