【问题标题】:Difference between __proto__ and prototype [duplicate]__proto__ 和原型之间的区别 [重复]
【发布时间】:2021-01-26 22:13:33
【问题描述】:

我试图澄清prototype__proto__ 的区别。 __proto__ 是否总是指向父母的prototype

所以Array.prototype 将包含concat() 等方法。 而Array.__proto__ 将指向 Array 的父/基对象上的方法?

【问题讨论】:

  • 最好不要完全怀疑__proto__,因为它已被弃用。请改用Object.getPrototypeOf()
  • 不清楚你所说的“父母”是什么意思,所以我会勉强说

标签: javascript


【解决方案1】:

TL:DR

__proto__ 是一个遗留功能,通常应避免使用MDN

什么是__proto__

简单地说,__proto__ 只是一个 propertyKey。这就是您应该看到的所有内容,因为虽然大多数内置对象之间存在共同行为,但它绝不是必须(甚至应该)以任何特定方式表现的东西。

将其视为常规的 getter/setter 对

我们可以轻松地使任何键的行为方式与__proto__ 相同:

const provingAPoint = {
  get thisIsANormalKey () { return Reflect.getPrototypeOf(this) },
  set thisIsANormalKey (proto) { Reflect.setPrototypeOf(this, proto) }
}

这基本上就是__proto__ 的全部内容。

始终期望对象与默认的 __proto__ 行为不同

如果您从某个 API 接收对象,则不应期望 __proto__ 的行为与默认对象中的行为相同。看上面的例子,很明显它不是一个可靠的东西。例如,我们可以这样做:

Reflect.defineProperty(provingAPoint, '__proto__', {
  get: () => { throw new Error('you are not getting my prototype like this') },
  set: () => { throw new Error('you will not set my prototype like this') }
})

现在如果有人试图访问这个属性,他们会得到一个错误。它现在也是只读的,不能更改或删除。

改用正确的方法

全局对象ObjectReflect 都具有静态方法getPrototypeOfsetPrototypeOf(关于Reflect 的细节不再赘述,它们的区别)。如果您要操作原型链,请使用这些

__proto__ 在当今 Java/EcmaScript 中的单一有效用法

令人惊讶的是,有一种有效的用途并不为人所知。创建对象字面量时,如果在其上定义 __proto__ 属性,如果其值为对象或 null,则生成的对象将使用该值作为原型

// this can save you some of the annoyances of `Object.create(null, {...descriptors})`
const objectWithNullPrototype = {
  __proto__: null,
  propA: 'valueA',
  prop0: 'value0'
}

Object.getPrototypeOf(objectWithNullPrototype) // => `null`
// and again, don't extect any consistent behaviour of `__proto__` because:
objectWithNullPrototype.__proto__ // => `undefined`

关于prototype

函数上的prototype 属性定义了构造对象时继承的内容

总之

一个构造函数prototype属性等于它构造的对象的原型。例如:

Object.getPrototypeOf(new Array(12)) === Array.prototype // => true
// NOTE: don't do this, use literals or `Object.create`
Object.getPrototypeOf(new Object()) === Object.prototype // => true
Object.getPrototypeOf(new Map()) === Map.prototype // => true

Java/EcmaScript 是一种基于原型的语言

如果您对这意味着什么有任何疑问,我强烈建议您 google 并阅读一些有关它的文章,因为对含义的误解(或不知道)是错误和混淆的常见来源。

【讨论】:

    【解决方案2】:

    有问题的主题 __proto__ 已被弃用,即使可用,也非常缓慢且不推荐使用。

    但是,它是一个访问器属性1,它公开了访问它的内部对象!

    但是,如果您阅读了 MDN 的以下文本,here,那么它会告诉您如何以及为什么实现它,即使它从未打算添加。

    长话短说,虽然它是一个 getter/setter 并且不直接连接到对象,但几乎在任何情况下,不要使用它

    【讨论】:

    • @Liam 走错路了。 __proto__ 是标准化的(以便需要实现它以实现 Web 兼容性的浏览器一致地实现它),但同时它是 explicitly deprecated in that standard 有利于现代 Object.get/setPrototopeOf
    猜你喜欢
    • 2015-09-29
    • 1970-01-01
    • 2021-10-27
    • 2014-08-16
    • 2011-04-08
    • 2012-11-24
    • 2013-06-05
    • 2021-09-29
    • 2020-05-27
    相关资源
    最近更新 更多