【问题标题】:Why __proto__ reference name look like wrong for inherited object? [duplicate]为什么 __proto__ 引用名称对于继承的对象看起来是错误的? [复制]
【发布时间】:2021-05-09 09:45:45
【问题描述】:
class Human{
    talk(){
        return 'talking';
    }
}
class SuperHuman extends Human{
    constructor(){
        super();
        this.age = 12;
    }
    fly(){
        return 'flying';
    }
}
let me = new Human();
let you = new SuperHuman();
you.gender = 'male';
console.log(you);
let she = Object.create(you);
console.log(she);

在研究原型继承时,she(object) proto 看起来像这样。

但我的期望是它应该看起来像这样......

为什么会这样显示?

【问题讨论】:

  • 嗨!请将代码、错误消息、标记和其他文本信息作为文本发布,而不是作为文本的图片。为什么:meta.stackoverflow.com/q/285551/157247
  • 老实说,我也觉得这很令人困惑。不知道为什么 Chrome 开发工具选择在那里显示 .__proto__.constructor.name
  • @JonasWilms - 它显示(松散地说)__proto__ 所指的对象的 type 或种类。
  • @t.j。是的,但实际上这是层次结构中的下一个对象。我希望任何查看该层次结构的人都熟悉原型链,这种“类型”更像是类思维。我认为 devtools 在这里以一种令人困惑的方式混合了两个概念。
  • @JonasWilms - 哦,我同意这很令人困惑——当然我不止一次被它困惑过。 :-) 另外,他们真的不应该使用__proto__,他们的意思是[[Prototype]]。 :-)

标签: javascript inheritance ecmascript-6 properties v8


【解决方案1】:

Devtools 只是告诉你she 的原型是a SuperHuman(具体来说,you),而不是原型是函数SuperHuman

she的原型链是:

she −> you −> SuperHuman.prototype −> Human.prototype −> Object.prototype
  • she 的原型是 you,因为您使用 Object.create(you) 创建它。
  • you 的原型是 SuperHuman.prototype,因为您使用 new SuperHuman 创建了它。
  • SuperHuman.prototype 的原型是 Human.prototype,因为您通过 class SuperHuman extends Human 创建了 SuperHuman 函数,该函数设置了两条继承链(一个用于 prototype 对象,另一个用于函数本身)。
  • Human.prototype 的原型是 Object.prototype,因为当没有 extends 时,class 就是这样做的。

顺便说一句,不幸的是,一些开发工具实现(例如基于 Chromium 的浏览器中的实现)使用__proto__,它们的意思是[[Prototype]]。一方面,它鼓励使用__proto__,这是不应该的(并非所有对象都有它并且它可以被遮蔽;总是使用Object.getPrototypeOfObject.setPrototypeOf)。另外,它具有误导性:Chromium 的 devtools 会很高兴地向您显示 __proto__ 一个根本没有 __proto__ 访问器属性的对象,因为它不继承自 Object.prototype (这是访问器的来源):

// An object with no prototype
const p = Object.create(null);

// An object using that as its prototype
const c = Object.create(p);

// An object inheriting from Object.prototype has the `__proto__` accessor property:
console.log("__proto__" in {}); // true

// `c` does not have the `__proto__` accessor property:
console.log("__proto__" in c); // false

// And yet, Chromium's devtools show you one if you expand it in the console
console.log(c);
Look in the real browser console.

【讨论】:

  • 对于它的价值,我在我最近一本书 JavaScript: The New Toys的第 4 章中详细介绍了由 class 语法建立的继承链>。如果您有兴趣,请在我的个人资料中链接。
  • "不幸的是,一些 devtools 实现使用__proto__,它们的意思是[[Prototype]]" - 完全同意。他们已经对其他内部结构使用了括号语法,那么为什么不在这里呢? bugs.chromium.org/p/chromium/issues/detail?id=817305
猜你喜欢
  • 2020-07-16
  • 1970-01-01
  • 2020-07-30
  • 1970-01-01
  • 1970-01-01
  • 2020-03-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多