这张图再次表明,每个对象都有一个原型。构造函数 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年)。


当前回答

正如这句话所说

__proto__是用于查找链的实际对象 原型是用来构建的对象 当你用new创建一个对象时: (新的Foo)。__proto__ === Foo.prototype; (新的Foo)。原型=== undefined;

我们可以进一步注意到,使用函数构造函数创建的对象的__proto__属性指向相应构造函数的prototype属性所指向的内存位置。

如果我们改变构造函数的prototype的内存位置,派生对象的__proto__仍将继续指向原始地址空间。因此,要使公共属性沿着继承链向下可用,总是将属性附加到构造函数函数原型,而不是重新初始化它(这会改变它的内存地址)。

考虑下面的例子:

function Human(){
    this.speed = 25;
}

var himansh = new Human();

Human.prototype.showSpeed = function(){
    return this.speed;
}

himansh.__proto__ === Human.prototype;  //true
himansh.showSpeed();    //25

//now re-initialzing the Human.prototype aka changing its memory location
Human.prototype = {lhs: 2, rhs:3}

//himansh.__proto__ will still continue to point towards the same original memory location. 

himansh.__proto__ === Human.prototype;  //false
himansh.showSpeed();    //25

其他回答

只有一个对象用于原型链接。该对象显然有一个名称和值:__proto__是它的名称,prototype是它的值。这是所有。

为了让它更容易理解,看看这篇文章顶部的图表(由dmitry soshnikov绘制的图表),你永远不会发现__proto__的值指向prototype以外的其他东西。

要点是:__proto__是引用原型对象的名称,prototype是实际的原型对象。

这就像是在说:

let x = {name: 'john'};

X是对象名称(指针),{name: 'john'}是实际对象(数据值)。

注意:这只是一个非常简单的提示,说明它们在较高的水平上是如何相互关联的。

更新:下面是一个简单具体的javascript示例,以便更好地说明:

let x = new String("testing") // Or any other javascript object you want to create

Object.getPrototypeOf(x) === x.__proto__; // true

这意味着当Object.getPrototypeOf(x)为我们获取x的实际值(这是它的原型)时,正是x的__proto__所指向的。因此__proto__确实指向x的原型。因此__proto__引用x (x的指针),而prototype是x的值(它的原型)。

我希望现在大家都明白了。

__proto__是在查找链中用于解析方法的实际对象,prototype是在你用new创建对象时用于构建__proto__的对象:

( new Foo ).__proto__ === Foo.prototype
( new Foo ).prototype === undefined

prototype是Function对象的一个属性。它是由该函数构造的对象的原型。

__proto__是一个对象的内部属性,指向它的原型。当前标准提供了等效的Object.getPrototypeOf(obj)方法,尽管事实上的标准__proto__更快。

你可以通过比较函数的原型和对象的__proto__链来找到instanceof关系,你也可以通过改变prototype来打破这些关系。

function Point(x, y) {
    this.x = x;
    this.y = y;
}

var myPoint = new Point();

// the following are all true
myPoint.__proto__ == Point.prototype
myPoint.__proto__.__proto__ == Object.prototype
myPoint instanceof Point;
myPoint instanceof Object;

这里Point是一个构造函数,它程序化地构建一个对象(数据结构)。myPoint是一个由Point()构造的对象,所以Point。原型保存到myPoint。解析:句意:在那个时候。

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

我们必须考虑的第一件事是,当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属性。这就是原型继承的实现方式。

__proto__是构造prototype和构造函数的基础,例如:function human(){}拥有prototype,该prototype在构造函数的新实例中通过__proto__共享。这里有更详细的阅读