这张图再次表明,每个对象都有一个原型。构造函数 function Foo也有自己的__proto__,也就是function .prototype, 而它又通过__proto__属性再次引用 Object.prototype。因此,重复,Foo。原型只是一个显式 Foo的属性,引用b和c对象的原型。

var b = new Foo(20);
var c = new Foo(30);

__proto__和prototype之间有什么区别?

这一数据来自dmitrysoshnikov.com网站。

注:上述2010年的文章现在有第二版(2017年)。


当前回答

我为自己画了一个小图,代表以下代码片段:

var Cat = function() {}
var tom = new Cat()

我有经典的OO背景,所以用这种方式表示层次结构很有帮助。为了帮助您阅读此图表,请将图像中的矩形视为JavaScript对象。是的,函数也是对象。;)

JavaScript中的对象有属性,__proto__只是其中之一。

此属性背后的思想是指向(继承)层次结构中的祖先对象。

JavaScript的根对象是object。Prototype和所有其他对象都是这个对象的后代。根对象的__proto__属性为null,表示继承链的结束。

你会注意到原型是函数的属性。Cat是一个函数,但function和Object也是(本机)函数。Tom不是一个函数,因此它没有这个属性。

此属性背后的思想是指向一个将在构造中使用的对象,即当您在该函数上调用new操作符时。

注意,原型对象(黄色矩形)有另一个属性称为 构造函数,它指向各自的函数对象。为 简短的原因,这是没有描述。

实际上,当我们用new Cat()创建tom对象时,所创建的对象的__proto__属性将被设置为构造函数的原型对象。

最后,让我们稍微研究一下这个图表。以下陈述是正确的:

汤姆。__proto__属性指向与Cat.prototype相同的对象。 猫。__proto__指向函数。原型对象,就像函数一样。__proto__和Object。__proto__做。 Cat.prototype。__proto__和tom.__proto__。__proto__指向相同的对象,即object .prototype。

干杯!

其他回答

'use strict'
function A() {}
var a = new A();
class B extends A {}
var b = new B();
console.log('====='); // =====
console.log(B.__proto__ === A); // true
console.log(B.prototype.__proto__ === A.prototype); // true
console.log(b.__proto__ === B.prototype); // true
console.log(a.__proto__ === A.prototype); // true
console.log(A.__proto__ === Function.__proto__); // true
console.log(Object.__proto__ === Function.__proto__); // true
console.log(Object.prototype === Function.__proto__.__proto__); // true
console.log(Object.prototype.__proto__ === null); // true

在JavaScript中,每个对象(函数也是对象!)都有__proto__属性,该属性是对其原型的引用。

当我们使用new操作符和构造函数一起创建一个新对象时, 新对象的__proto__属性将被设置为构造函数的prototype属性, 然后构造函数将由new对象调用, 在这个过程中,“this”将是构造函数作用域中对新对象的引用,最终返回新对象。

构造函数的prototype是__proto__属性,构造函数的prototype属性是work with new操作符。

构造函数必须是函数,但函数并不总是构造函数,即使它具有prototype属性。

Prototype chain实际上是对象的__proto__属性,用于引用其原型, 以及原型的__proto__属性来引用原型的原型,等等, 直到引用Object的原型的__proto__属性,该属性引用为null。

例如:

console.log(a.constructor === A); // true
// "a" don't have constructor,
// so it reference to A.prototype by its ``__proto__`` property,
// and found constructor is reference to A

[[Prototype]]和__proto__属性实际上是一样的。

我们可以使用Object的getPrototypeOf方法来获取某个对象的原型。

console.log(Object.getPrototypeOf(a) === a.__proto__); // true

我们编写的任何函数都可以用new操作符创建一个对象, 这些函数中的任何一个都可以是构造函数。

这个问题有很多很好的答案,但为了概括和紧凑形式的答案,我添加了以下内容:

我们必须考虑的第一件事是,当JS发明的时候,计算机的内存非常低,所以如果我们需要一个进程来创建新的对象类型,我们必须考虑内存性能。

因此,他们在内存的独立部分,定位由特定对象类型创建的对象需要的方法,而不是每次我们创建一个新对象时,在对象之外存储方法。 因此,如果我们用JS的新特性重新定义新的运算符和构造函数概念,我们有以下步骤:

和空对象。(这将是对象类型实例化的最终结果)

let empty={}

我们已经知道,由于内存性能原因,对象类型实例所需的所有方法都位于构造函数的prototype属性上。(函数也是对象,所以它们可以有属性) 因此,我们将空对象的__protp__引用到这些方法存在的位置。 (我们将概念上作为构造函数使用的函数命名为构造函数。

empty.__proto__ = constructor.prototype

我们必须初始化对象类型值。 在JS中的函数与对象断开连接。使用点表示法或函数对象的bind call apply等方法,我们必须知道“函数的上下文是什么”。

let newFunc = constructor.bind(empty)

现在我们有了一个新函数,它有一个空对象作为这个context。 执行此函数后。空对象将被填充,如果定义的构造函数函数没有返回,类型object的实例化结果将是这个空对象(就好像这将是该过程的结果一样)

所以正如你所看到的,__proto__是一个对象的属性,它引用了其他对象(在JS中函数也是对象)原型对象属性,它由跨特定对象类型的实例使用的属性组成。

正如你可以从短语中猜到的那样,函数是对象,函数也有__proto__属性,因此它们可以引用其他对象的prototype属性。这就是原型继承的实现方式。

简单来说:

> var a = 1
undefined
> a.__proto__
[Number: 0]
> Number.prototype
[Number: 0]
> Number.prototype === a.__proto__
true

这允许你在X类型的对象实例化之后将属性附加到X.prototype,并且它们仍然可以通过javascript引擎使用的__proto__引用访问这些新属性。

(函数(){ Let a = function(){console.log(this.b)}; A.prototype.b = 1; a.__proto__。B = 2; 设q = new a(); console.log (a.b); console.log (q.b) }) ()

试着理解这段代码

我试试四年级的解释:

事情很简单。原型是如何构建某样东西的例子。所以:

我是一个函数,我构建与原型相似的新对象 我是一个对象,我是用我的__proto__作为例子来构建的

证明:

function Foo() { }

var bar = new Foo()

// `bar` is constructed from how Foo knows to construct objects
bar.__proto__ === Foo.prototype // => true

// bar is an instance - it does not know how to create objects
bar.prototype // => undefined