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


当前回答

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。解析:句意:在那个时候。

其他回答

一种很好的思考方式是……

Prototype用于构造函数。它真的应该被称为“prototypeToInstall”,因为它就是这样的。

__proto__是对象上的“已安装原型”(由上述构造函数()函数创建/安装在对象上)

除了以上这些精彩的答案外,我还想说得更清楚一点:

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

var eve = new Person("Eve");

eve.__proto__ == Person.prototype //true

eve.prototype  //undefined

实例有__proto__,类有prototype。

我认为你需要知道__proto__, [[prototype]]和prototype之间的区别。

公认的答案是有帮助的,但它可能暗示(不完全)__proto__只与在构造函数上使用new创建的对象相关,这是不正确的。

更准确地说:__proto__存在于每个对象上。

But what is __proto__ at all? Well, it is an object referencing another object which is also a property of all objects, called [[prototype]]. It's worth mentioning that [[prototype]] is something that JavaScript handles internally and is inaccessible to the developer. Why would we need a reference object to the property [[prototype]] (of all objects)? Because JavaScript doesn't want to allow getting / setting the [[prototype]] directly, so it allows it through a middle layer which is __proto__. So you can think of __proto__ as a getter/setter of the [[prototype]] property. What is prototype then? It is something specific to functions(Initially defined in Function, i.e, Function.prototype and then prototypically inherited by newly created functions, and then again those functions give it to their children, forming a chain of prototypical inheritance). JavaScript uses a parent function's prototype to set its child functions' [[prototype]] when that parent function is run with new (remember we said all objects have [[prototype]]? well, functions are objects too, so they have [[prototype]] as well). So when the [[prototype]] of a function(child) is set to the prototype of another function(parent), you will have this in the end: let child = new Parent(); child.__proto__ === Parent.prototype // --> true. (Remember child.[[prototype]] is inaccessible, so we checked it using __proto__.)


注意1:只要属性不在子对象中,它的__proto__将被“隐式”搜索。例如,if child。Myprop返回一个值,你不能说" Myprop "是子对象的属性,还是父对象原型的属性。这也意味着你永远不需要做这样的事情:child.__proto__.__proto__。我的东西你自己拿去吧,孩子。Myprop会自动为你做这件事。

注意2:即使父对象的原型中有项目,子对象自己的原型最初也是一个空对象。如果您想进一步扩展继承链(将child[ren]添加到child),则可以向其中添加项或手动从其中删除项。或者可以隐式地操纵它,例如使用类语法。)

注意3:如果你需要自己设置/获取[[prototype]],使用__proto__有点过时,现代JavaScript建议使用Object。setPrototypeOf和Object。getPrototypeOf代替。

我知道,我迟到了,但让我试着简化一下。

假设有一个函数

    function Foo(message){

         this.message = message ; 
     };

     console.log(Foo.prototype);

Foo函数将有一个原型对象链接。所以,无论何时我们在JavaScript中创建一个函数,它总是有一个原型对象链接到它。

现在让我们继续使用函数Foo创建两个对象。

    var a = new Foo("a");
    var b = new Foo("b");
    console.log(a.message);
    console.log(b.message);

现在我们有两个对象,对象a和对象b。它们都被创建了 使用构造函数Foo。记住,构造函数在这里只是一个词。 对象a和b都有message属性的副本。 这两个对象a和b链接到构造函数Foo的原型对象。 在对象a和b上,我们可以在所有浏览器中使用__proto__属性访问Foo prototype,在IE中我们可以使用Object.getPrototypeOf(a)或Object.getPrototypeOf(b)

现在,Foo。Prototype, a.__proto__和b.__proto__都表示同一个对象。

    b.__proto__ === Object.getPrototypeOf(a);
    a.__proto__ ===  Foo.prototype;
    a.constructor.prototype  === a.__proto__;

所有这些都将返回true。

如我们所知,在JavaScript中属性可以动态添加。我们可以向对象添加属性

    Foo.prototype.Greet = function(){

         console.log(this.message);
    }
    a.Greet();//a
    b.Greet();//b
    a.constructor.prototype.Greet();//undefined 

如你所见,我们在Foo中添加了Greet()方法。但它可以在a和b或任何其他使用Foo构造的对象中访问。

在执行a.Greet()时,JavaScript将首先在对象a的属性列表中搜索Greet。如果没有找到,它将在a. Since a.__proto__和Foo的__proto__链中上升。prototype是同一个对象,JavaScript会找到Greet()方法并执行它。

我希望,现在prototype和__proto__被简化了一点。

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

 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”。