这张图再次表明,每个对象都有一个原型。构造函数 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__作为例子来构建的

证明:

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

其他回答

原型

prototype是一个函数的属性。它是通过使用带有new关键字的that(构造函数)函数创建对象的蓝图。

__proto__

__proto__在查找链中用于解析方法、属性。当创建对象时(使用构造函数函数和new关键字),__proto__被设置为(构造函数)function .prototype

function Robot(name) {
    this.name = name;
}
var robot = new Robot();

// the following are true   
robot.__proto__ == Robot.prototype
robot.__proto__.__proto__ == Object.prototype

以下是我的(假想的)解释,以消除困惑:

假设有一个与函数相关的假想类(blueprint/ cookie cutter)。那个假想类用于实例化对象。prototype是一种扩展机制(c#或Swift Extension中的扩展方法),用于向虚类中添加内容。

function Robot(name) {
    this.name = name;
}

以上可以想象为:

// imaginary class
class Robot extends Object{

    static prototype = Robot.class  
    // Robot.prototype is the way to add things to Robot class
    // since Robot extends Object, therefore Robot.prototype.__proto__ == Object.prototype

    var __proto__;

    var name = "";

    // constructor
    function Robot(name) {

        this.__proto__ = prototype;
        prototype = undefined;

        this.name = name;
    }

} 

So,

var robot = new Robot();

robot.__proto__ == Robot.prototype
robot.prototype == undefined
robot.__proto__.__proto__ == Object.prototype

现在为Robot的原型添加方法:

Robot.prototype.move(x, y) = function(x, y){ Robot.position.x = x; Robot.position.y = y};
// Robot.prototype.move(x, y) ===(imagining)===> Robot.class.move(x, y)

以上可以想象为Robot类的扩展:

// Swift way of extention
extension Robot{
    function move(x, y){    
        Robot.position.x = x; Robot.position.y = y
    }
}

反过来,

// imaginary class
class Robot{

    static prototype = Robot.class // Robot.prototype way to extend Robot class
    var __proto__;

    var name = "";

    // constructor
    function Robot(name) {

        this.__proto__ = prototype;
        prototype = undefined;

        this.name = name;
    }

    // added by prototype (as like C# extension method)
    function move(x, y){ 
        Robot.position.x = x; Robot.position.y = y
    };
}

为了解释,让我们创建一个函数

 function a (name) {
  this.name = name;
 }

当JavaScript执行这段代码时,它将prototype属性添加到。prototype属性是一个具有两个属性的对象:

构造函数 __proto__

所以当我们这样做的时候

a.原型它返回

     constructor: a  // function definition
    __proto__: Object

现在你可以看到构造函数就是函数a本身 而__proto__指向JavaScript的根对象。

让我们看看当我们使用带有new关键字的函数时会发生什么。

var b = new a ('JavaScript');

当JavaScript执行这段代码时,它会做4件事:

它创建了一个新对象,一个空对象// {} 它在b上创建__proto__,并使其指向a.prototype,因此b.__proto__ === a.prototype 它使用新创建的对象(在步骤#1中创建)作为上下文(this)执行a.p otype.constructor(这是函数a的定义),因此作为'JavaScript'传递的name属性(它被添加到this)被添加到新创建的对象。 它返回新创建的对象(在步骤#1中创建),因此var b被分配给新创建的对象。

现在如果我们添加a.prototype。car = "BMW"然后 b.car,输出“BMW”出现。

这是因为当JavaScript执行这段代码时,它在b上搜索car属性,它没有发现,然后JavaScript使用b.__proto__(在步骤#2中指向“a.prototype”)并找到car属性,因此返回“BMW”。

在JavaScript中,函数可以用作构造函数。这意味着我们可以使用new关键字从它们中创建对象。每个构造函数都带有一个内置对象。这个内置对象称为原型。构造函数的实例使用__proto__来访问其构造函数的prototype属性。

First we created a constructor: function Foo(){}. To be clear, Foo is just another function. But we can create an object from it with the new keyword. That's why we call it the constructor function Every function has a unique property which is called the prototype property. So, Constructor function Foo has a prototype property which points to its prototype, which is Foo.prototype (see image). Constructor functions are themselves a function which is an instance of a system constructor called the [[Function]] constructor. So we can say that function Foo is constructed by a [[Function]] constructor. So, __proto__ of our Foo function will point to the prototype of its constructor, which is Function.prototype. Function.prototype is itself is nothing but an object which is constructed from another system constructor called [[Object]]. So, [[Object]] is the constructor of Function.prototype. So, we can say Function.prototype is an instance of [[Object]]. So __proto__ of Function.prototype points to Object.prototype. Object.prototype is the last man standing in the prototype chain. I mean it has not been constructed. It's already there in the system. So its __proto__ points to null. Now we come to instances of Foo. When we create an instance using new Foo(), it creates a new object which is an instance of Foo. That means Foo is the constructor of these instances. Here we created two instances (x and y). __proto__ of x and y thus points to Foo.prototype.

解释性的例子:

function Dog(){}
Dog.prototype.bark = "woof"

let myPuppie = new Dog()

现在,myPupppie有__proto__属性指向Dog.prototype。

> myPuppie.__proto__
>> {bark: "woof", constructor: ƒ}

但是mypuppy没有原型属性。

> myPuppie.prototype
>> undefined

因此,mypuppie的__proto__是对用于实例化此对象的构造函数的.prototype属性的引用(当前mypuppie对象与此__proto__对象具有“委托”关系),而mypuppie的.prototype属性则根本不存在(因为我们没有设置它)。

MPJ的解释很好: 在JavaScript中创建对象

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

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