javascript - 原型(prototype)和 __proto__,哪种说法是正确的?

标签 javascript prototype

我正在尝试理解 JavaScript 中基于原型(prototype)的继承。我读了很多书并用谷歌搜索了几个小时。现在,我需要连接所有这些信息,希望你能帮助我。

如果以下 3 个陈述正确:

  • JavaScript 中的每个对象都有一个特殊的内部属性,我们可以通过 .__proto__ 访问该属性。 .
  • 所有构造函数都有一个匿名对象属性,我们可以通过 .protootype 访问该属性。 .
  • __proto__ 实例对象的属性指向 prototype构造函数的对象属性。

让我们创建以下构造函数,该函数创建一个 Dog 对象:

function Dog(name, color) {
  this.name = name;
  this.color = color;

  this.bark = function() {
    return `Bark, bark! My name is ${this.name}`;
  }
}

现在让我们创建一个 Dog 对象的实例:

let mini = new Dog('mini', 'black');

如果我们现在打开控制台并返回mini,结果如下:

enter image description here

正如预期的那样,实例对象 mini 继承了其构造函数的所有属性和方法。

但是这些继承的属性和方法都不在其 __proto__ 内。属性(property)。看起来它们都是直接继承到对象 mini 本身的。

现在让我们向构造函数的原型(prototype)对象添加一个新方法:

Dog.prototype.myBread = function() {
  return `My bread is ${this.bread}`;
}

如果我们现在在控制台中返回 mini,我们会得到以下结果:

enter image description here

同样,正如预期的那样,新方法 myBread 被传递给我们的对象。但这一次它显示在 __proto__ 内我们的对象 mini,它引用(指向)构造函数内的 prototype 对象 属性。

现在,根据上面的简单实验,我假设以下内容:

  1. 如果构造函数有自己的属性和方法,则它们不是其原型(prototype)对象的一部分。这些属性和方法直接位于构造函数对象上。

  2. 但是如果我们向 .protoype 添加属性或方法构造函数中,它们被添加到其原型(prototype)对象中。为了证明这一点,我们无法访问Dog.myBread();但我们可以访问Dog.prototype.myBread();

  3. 添加到 .prototype 的属性和方法我们的构造函数着陆到构造函数的原型(prototype)对象,并且因为 __proto__我们的实例对象引用该原型(prototype)对象,我们可以在实例对象中访问它们。

  4. 如果构造函数有自己的属性和方法,则它们不在其原型(prototype)对象内部。这些属性和方法直接位于对象上,并自动传递给其所有实例。在这种情况下 __proto__prototype属性不发挥任何作用,与继承过程无关!

现在,你能帮我看看我的假设是否正确吗? 我对最后一个假设特别好奇。

最佳答案

Each object in JavaScript has a special internal property that we can access via .__proto__

没有。每个 JS 对象都有一个内部 [[prototype]] 链接,我们可以通过 Object.getPrototypeOf() 访问它。 __proto__ 已弃用,并且不适用于所有对象。

All constructor functions have an anonymous object property, which we can access via .protootype.

是的,所有构造函数都有一个带有对象的 .prototype 属性,但我不确定为什么您将其称为“匿名”。

The [[prototype]] link of an instance object points to the prototype object property of its constructor.

不是针对属性,而是针对对象本身。如果您重新分配 Constructor.prototype = ...,实例的 [[prototype]] 链接不会更改。当您调用 new 时,会使用 Constructor.prototype 的当前值设置链接,是的。

<小时/>

As expected the instance object mini has inherited all properties and methods of it's constructor.

不,您的第一个示例中没有继承。 barkcolorname 属性由实例拥有。它们不属于构造函数,它们只是由实例上的构造函数代码创建的。

  1. If a constructor has its own properties and methods, they are not part of its prototype object. Those properties and methods sit directly on the constructor object.

是的,.prototype.name 就是位于构造函数对象本身的属性。

(请注意,作为函数对象的每个构造函数也有一个指向 Function.prototype 的 [[prototype]] 链接,但这在这里并不是特别有趣)

  1. But if we add properties or methods to .protoype of a constructor, they get added to its prototype object. To prove it, we cannot access Dog.myBread(); but we can access Dog.prototype.myBread();

这听起来像是老生常谈,所以是的。

  1. Properties and methods, that are added to the .prototype of our constructor land in to the prototype object of the constructor and because the [[prototype]] of our instance object references that prototype object, we can access them in our instance object.

是的,这就是继承。

  1. If a constructor has its own properties and methods, they are not inside its prototype object. Those properties and methods sit directly on the object and are passed automatically to all its instances. In such case the __proto__ and prototype property don't play any role and have nothing to do with the inheritance process!

是的,自己的属性与继承无关。

关于javascript - 原型(prototype)和 __proto__,哪种说法是正确的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51522415/

相关文章:

javascript - Shiny 的条件面板 : condition based on class of variable in a dataset

javascript - 返回包含 javascript 的部分 View 是不好的做法吗?

javascript - ASP.NET MVC如何理解相关技术,javascript、html、css

javascript - 如果我使用非类/原型(prototype)方法 : Origin file://is not allowed by Access-Control-Allow-Origin,则不会发生此错误

javascript - 为什么当我已经设置了对象属性时,它们仍未定义

javascript - 为什么 console.log 显示错误属性?

javascript - 使用 Parse 平台在查询中选择嵌套字段

javascript - 选择和关注网页元素不起作用(偏移)

Javascript 'Namespaces' 和 jQuery AJAX

javascript - 在通过 Object.create 创建的对象上设置原型(prototype)