__proto__ VS. JavaScript中的原型

__proto__ VS. prototype in JavaScript

This figure again shows that every object has a prototype. Constructor
function Foo also has its own __proto__ which is Function.prototype,
and which in turn also references via its __proto__ property again to
the Object.prototype. Thus, repeat, Foo.prototype is just an explicit
property of Foo which refers to the prototype of b and c objects.

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

__proto__prototype属性之间有什么区别?

enter image description here

这个数字来自这里。


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

1
2
( new Foo ).__proto__ === Foo.prototype;
( new Foo ).prototype === undefined;


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

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

您可以通过将函数的prototype与对象的__proto__链进行比较来找到instanceof关系,并且可以通过更改prototype来中断这些关系。

1
2
3
4
5
6
7
8
9
10
11
12
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.prototype在那时被保存到myPoint.__proto__


声明函数时会创建Prototype属性。

例如:

1
2
3
 function Person(dob){
    this.dob = dob
 };

一旦声明了上面的函数,就会在内部创建Person.prototype属性。
可以将许多属性添加到Person.prototype中,这些属性由使用新Person()创建的Person实例共享。

1
2
// adds a new method age to the Person.prototype Object.
Person.prototype.age = function(){return date-dob};

值得注意的是,默认情况下Person.prototypeObject文字(可以根据需要进行更改)。

使用new Person()创建的每个实例都有一个__proto__属性,该属性指向Person.prototype。这是用于遍历以查找特定对象的属性的链。

1
2
var person1 = new Person(somedate);
var person2 = new Person(somedate);

创建Person的2个实例,这两个对象可以将Person.prototypeage方法称为person1.ageperson2.age

在您问题的上图中,您可以看到FooFunction Object,因此它有__proto____proto__链接,而Function.prototype又是Object的一个实例并且有一个__proto__链接到Object.prototype。 proto链接在此处以Object.prototype中的__proto__指向null

任何对象都可以访问其原型链中由__proto__链接的所有属性,从而形成原型继承的基础。

__proto__不是访问原型链的标准方法,标准但类似的方法是使用Object.getPrototypeOf(obj)

下面的instanceof运算符代码可以更好地理解:

object instanceof当一个对象是一个Class的实例时,类运算符返回true,更具体地说,如果在该对象的proto链中找到Class.prototype,那么该对象就是该Class的一个实例。

1
2
3
4
5
6
7
8
9
function instanceOf(Func){
  var obj = this;
  while(obj !== null){
    if(Object.getPrototypeOf(obj) === Func.prototype)
      return true;
    obj = Object.getPrototypeOf(obj);
  }
  return false;
}

上面的方法可以被称为:instanceOf.call(object, Class)如果object是Class的实例,则返回true。


想到它的好方法是......

constructor()函数使用prototype。它应该被称为像"prototypeToInstall"这样的东西,因为它就是它的本质。

__proto__是对象的"已安装原型"(从constructor()函数创建/安装在对象上)


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

1
2
3
 function a (name) {
  this.name = name;
 }

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

  • constructor
  • __proto__
  • 所以,当我们这样做

    a.prototype它返回

    1
    2
         constructor: a  // function definition
        __proto__: Object

    现在你可以看到constructor只是函数a本身
    __proto__指向JavaScript的根级别Object

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

    1
    var b = new a ('JavaScript');

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

  • 它创建一个新对象,一个空对象// {}
  • 它在b上创建__proto__并使其指向a.prototype所以b.__proto__ === a.prototype
  • 它使用新创建的对象(在步骤#1中创建)作为其上下文(this)执行a.prototype.constructor(函数a的定义),因此name属性作为'JavaScript'传递(添加到this)被添加到新创建的对象中。
  • 它返回新创建的对象(在步骤#1中创建),因此var b被分配给新创建的对象。
  • 现在,如果我们添加a.prototype.car ="BMW"并做
    b.car,输出"BMW"出现。

    这是因为当JavaScript执行此代码时,它在b上搜索了car属性,它没有找到使用的JavaScript b.__proto__(在步骤#2中指向'a.prototype')并找到< x23>财产所以返回"宝马"。


    原型VS. __proto__ VS. [[原型]]

    在创建函数时,会自动创建一个名为prototype的属性对象(您自己没有创建它)并且正在附加到函数对象(constructor)。注意:这个新的原型对象也指向或具有本机JavaScript对象的内部私有链接。

    例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    function Foo () {
        this.name = 'John Doe';
    }

    // Foo has an object property called prototype.
    // prototype was created automatically when we declared the function Foo.
    Foo.hasOwnProperty('prototype'); // true

    // Now, we can assign properties and methods to it:
    Foo.prototype.myName = function () {
        return 'My name is ' + this.name;
    }

    如果你将使用new关键字从Foo创建一个新对象,你基本上创建一个新对象,它具有我们之前讨论过的函数原型Foo的内部或私有链接:

    1
    2
    3
    var b = new Foo();

    b.[[Prototype]] === Foo.prototype  // true

    该函数对象的私有链接称为双括号原型或只是[[Prototype]]。许多浏览器为我们提供了一个名为__proto__的公共链接!

    更具体地说,__proto__实际上是属于本机JavaScript对象的getter函数。它返回this绑定所在的内部私有原型链接(返回b[[Prototype]]):

    1
    b.__proto__ === Foo.prototype // true

    值得注意的是,从ECMAScript5开始,您还可以使用getPrototypeOf方法来获取内部私有链接:

    1
    Object.getPrototypeOf(b) === b.__proto__ // true

    注意:这个答案并不打算涵盖创建新对象或新构造函数的整个过程,而是为了帮助更好地理解__proto__prototype[[Prototype]]是什么以及它是如何工作的。


    除了上面的答案之外,还要清楚一点:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    function Person(name){
        this.name = name
     };

    var eve = new Person("Eve");

    eve.__proto__ == Person.prototype //true

    eve.prototype  //undefined

    实例有__proto__,类有原型。


    在JavaScript中,函数可以用作构造函数。这意味着我们可以使用new关键字从中创建对象。每个构造函数都带有一个与它们链接在一起的内置对象。这个内置对象称为原型。 Instances of a constructor function use __proto__ to access the prototype property of its constructor function.

    prototype diagram

  • 首先我们创建了一个构造函数:function Foo(){}。要清楚,Foo只是另一个功能。但我们可以使用new关键字从中创建一个对象。这就是我们称之为构造函数的原因

  • 每个函数都有一个唯一的属性,称为prototype属性。因此,构造函数Foo有一个原型属性,指向其原型,即Foo.prototype(见图)。

  • 构造函数本身就是一个函数,它是一个名为[[Function]]构造函数的系统构造函数的实例。所以我们可以说function Foo是由[[Function]]构造函数构造的。因此,Foo function__proto__将指向其构造函数的原型,即Function.prototype

  • Function.prototype本身只不过是一个从另一个名为[[Object]]的系统构造函数构造的对象。所以,[[Object]]Function.prototype的构造函数。所以,我们可以说Function.prototype[[Object]]的一个实例。所以__proto____proto__指向Object.prototype

  • Object.prototype是站在原型链中的最后一个人。我的意思是它还没有建成。它已经存在于系统中。所以它的__proto__指向null

  • 现在我们来到Foo的实例。当我们使用new Foo()创建实例时,它会创建一个新对象,它是Foo的一个实例。这意味着Foo是这些实例的构造函数。这里我们创建了两个实例(x和y)。因此,x和y的__proto__指向Foo.prototype


  • 我碰巧学习了你不知道JS的原型:这个&amp;对象原型,这是一本很好的书,可以理解下面的设计并澄清如此多的误解(这就是为什么我试图避免使用继承和instanceof之类的东西)。

    但我有同样的问题,就像人们在这里问的那样。几个答案真的很有帮助和启发。我也很想分享我的理解。

    什么是原型?

    JavaScript中的对象具有内部属性,在规范中表示为[[Prototype]],它只是对另一个对象的引用。在创建此属性时,几乎所有对象都被赋予非null值。

    如何获得对象的原型?

    via __proto__Object.getPrototypeOf

    1
    2
    3
    4
    5
    6
    7
    8
    var a = { name:"wendi" };
    a.__proto__ === Object.prototype // true
    Object.getPrototypeOf(a) === Object.prototype // true

    function Foo() {};
    var b = new Foo();
    b.__proto__ === Foo.prototype
    b.__proto__.__proto__ === Object.prototype

    什么是prototype

    prototype是一个自动创建的对象,它是一个函数的特殊属性,用于建立委托(继承)链,即原型链。

    当我们创建一个函数a时,prototype会自动创建为a上的特殊属性,并将函数代码保存为prototype上的constructor

    1
    2
    3
    function Foo() {};
    Foo.prototype // Object {constructor: function}
    Foo.prototype.constructor === Foo // true

    我很乐意将此属性视为存储函数对象的属性(包括方法)的位置。这也是为什么JS中的实用程序函数被定义为Array.prototype.forEach()Function.prototype.bind()Object.prototype.toString().的原因

    为什么要强调函数的属性?

    1
    2
    3
    4
    5
    6
    7
    {}.prototype // undefined;
    (function(){}).prototype // Object {constructor: function}

    // The example above shows object does not have the prototype property.
    // But we have Object.prototype, which implies an interesting fact that
    typeof Object ==="function"
    var obj = new Object();

    所以,AraryFunctionObject都是函数。我应该承认这会刷新我对JS的印象。我知道函数是JS中的一等公民,但它似乎是建立在函数之上的。

    __proto__prototype之间有什么区别?

    __proto__引用适用于每个对象以引用其[[Prototype]]属性。

    prototype是一个自动创建的对象,它是一个函数的特殊属性,用于存储函数对象的属性(包括方法)。

    有了这两个,我们就可以在精神上绘制原型链。如下图所示:

    >
</p>
<div class=

    1
    2
    3
    4
    5
    6
    function Foo() {}
    var b = new Foo();

    b.__proto__ === Foo.prototype // true
    Foo.__proto__ === Function.prototype // true
    Function.prototype.__proto__ === Object.prototype // true


    理解它的另一个好方法:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    var foo = {}

    /*
    foo.constructor is Object, so foo.constructor.prototype is actually
    Object.prototype; Object.prototype in return is what foo.__proto__ links to.
    */

    console.log(foo.constructor.prototype === foo.__proto__);
    // this proves what the above comment proclaims: Both statements evaluate to true.
    console.log(foo.__proto__ === Object.prototype);
    console.log(foo.constructor.prototype === Object.prototype);

    仅在支持IE11 __proto__之后。在该版本之前,例如IE9,您可以使用constructor来获取__proto__


    原型

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

    __proto__

    在查找链中使用__proto__来解析方法,属性。创建对象时(使用带有new关键字的构造函数),__proto__设置为(Constructor)Function.prototype

    1
    2
    3
    4
    5
    6
    7
    8
    function Robot(name) {
        this.name = name;
    }
    var robot = new Robot();

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

    这是我(假想的)解释清除混乱:

    想象一下,有一个与功能相关的想象类(蓝图/ coockie切割器)。该虚构类用于实例化对象。 prototype是扩展机制(C#中的扩展方法,或Swift扩展),用于向该虚构类添加内容。

    1
    2
    3
    function Robot(name) {
        this.name = name;
    }

    以上可以想象为:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    // 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;
        }

    }

    所以,

    1
    2
    3
    4
    5
    var robot = new Robot();

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

    现在添加方法到机器人的prototype

    1
    2
    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类的扩展:

    1
    2
    3
    4
    5
    6
    // Swift way of extention
    extension Robot{
        function move(x, y){    
            Robot.position.x = x; Robot.position.y = y
        }
    }

    反过来,

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    // 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
        };
    }


    摘要:

    对象的__proto__属性是映射到对象的构造函数的prototype的属性。换一种说法:

    instance.__proto__ === constructor.prototype // true

    这用于形成对象的prototype链。 prototype链是对象属性的查找机制。如果访问了对象的属性,JavaScript将首先查看对象本身。如果在那里找不到该属性,它将一直爬到protochain直到找到(或不是)

    例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    function Person (name, city) {
      this.name = name;
    }

    Person.prototype.age = 25;

    const willem = new Person('Willem');

    console.log(willem.__proto__ === Person.prototype); // the __proto__ property on the instance refers to the prototype of the constructor

    console.log(willem.age); // 25 doesn't find it at willem object but is present at prototype
    console.log(willem.__proto__.age); // now we are directly accessing the prototype of the Person function

    我们的第一个日志结果是true,这是因为如上所述,构造函数创建的实例的__proto__属性引用了构造函数的prototype属性。请记住,在JavaScript中,函数也是对象。对象可以具有属性,任何函数的默认属性都是名为prototype的一个属性。

    然后,当此函数用作构造函数时,从其实例化的对象将接收名为__proto__的属性。此__proto__属性引用构造函数的prototype属性(默认情况下每个函数都有)。

    为什么这有用?

    查找Objects上的属性时,JavaScript有一种机制,称为"原型继承",这里它基本上是这样做的:

    • 首先,检查属性是否位于Object本身。如果是,则返回此属性。
    • 如果属性不在对象本身上,它将"爬上原始链接"。它基本上是查看__proto__属性引用的对象。在那里,它检查属性是否在__proto__引用的对象上可用。
    • 如果属性不在__proto__对象上,它将爬上__proto__链,一直到Object对象。
    • 如果它无法在对象及其prototype链的任何位置找到该属性,则它将返回undefined

    例如:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    function Person (name) {
      this.name = name;
    }

    let mySelf = new Person('Willem');

    console.log(mySelf.__proto__ === Person.prototype);

    console.log(mySelf.__proto__.__proto__ === Object.prototype);


     JavaScript prototype vs __prototype__

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    '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属性设置,
    那么构造函数将被新对象调用,
    在那个进程中"this"将是对构造函数作用域中新对象的引用,最后返回新对象。

    构造函数的原型是__proto__属性,Constructor的prototype属性与new运算符一起使用。

    构造函数必须是一个函数,但即使函数具有prototype属性,函数也不总是构造函数。

    原型链实际上是对象的__proto__属性来引用它的原型,
    和原型的__proto__属性来引用原型的原型,依此类推,
    直到引用Object的原型的__proto__属性,该属性引用null。

    例如:

    1
    2
    3
    4
    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方法来获取原型。

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

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


    简而言之:

    1
    2
    3
    4
    5
    6
    7
    8
    > var a = 1
    undefined
    > a.__proto__
    [Number: 0]
    > Number.prototype
    [Number: 0]
    > Number.prototype === a.__proto__
    true

    这允许您将属性附加到X.prototype AFTER类型的对象已被实例化,并且他们仍然可以通过__proto__引用访问这些新属性,Javascript引擎用它来走原型链。


    Prototype或Object.prototype是对象文字的属性。它表示Object原型对象,您可以覆盖它以在原型链中进一步添加更多属性或方法。

    __proto__是一个访问器属性(get和set函数),它公开了访问它的对象的内部原型。

    参考文献:

  • https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/prototype
  • http://www.w3schools.com/js/js_object_prototypes.asp

  • https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/proto


  • 我知道,我迟到但让我试着简化它。

    让我们说有一个功能

    1
    2
    3
    4
    5
    6
        function Foo(message){

             this.message = message ;
         };

         console.log(Foo.prototype);

    Foo函数将链接原型对象。因此,每当我们在JavaScript中创建一个函数时,它总是有一个链接到它的原型对象。

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

    1
    2
    3
    4
        var a = new Foo("a");
        var b = new Foo("b");
        console.log(a.message);
        console.log(b.message);
  • 现在我们有两个对象,对象a和对象b。两者都是创造的
    使用构造函数Foo。请记住构造函数在这里只是一个词。
  • 对象a和b都有一个消息属性的副本。
  • 这两个对象a和b链接到构造函数Foo的原型对象。
  • 在对象a和b上,我们可以在所有浏览器中使用proto属性访问Foo原型,在IE中我们可以使用Object.getPrototypeOf(a)或Object.getPrototypeOf(b)
  • 现在,Foo.prototype,a.proto和b.proto都表示相同的对象。

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

    以上所有都将返回true。

    众所周知,JavaScript属性可以动态添加。我们可以添加属性到对象

    1
    2
    3
    4
    5
    6
    7
        Foo.prototype.Greet = function(){

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

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

    在执行a.Greet()时,JavaScript将首先在对象a属性列表中搜索Greet。如果没有找到,它将会进入原型链。由于a.proto和Foo.prototype是同一个对象,JavaScript会找到Greet()方法并执行它。

    我希望,现在原型和proto有点简化了。


    定义

    (括号()内的数字是下面写的代码的"链接")

    prototype - 包含以下内容的对象:
    =>函数(3)
    特别是ConstructorFunction.prototype(5),每个人都可以访问
    object(4)通过这个构造函数创建或创建(1)
    =>构造函数本身(1)
    => __proto__此特定对象(原型对象)

    __proto__(dandor proto?) - 通过特定构造函数(1)创建的任何对象(2)与该构造函数的原型对象属性(5)的链接允许每个创建的对象(2)有权访问原型的函数和方法(4)(__proto__默认包含在JS中的每个对象中)

    代码澄清

    1。

    1
    2
    3
    4
        function Person (name, age) {
            this.name = name;
            this.age = age;  ?
        }

    2。

    1
    2
        var John = new Person(‘John’, 37);
        // John is an object

    3。

    1
    2
    3
    4
        Person.prototype.getOlder = function() {
            this.age++;
        }
        // getOlder is a key that has a value of the function

    4。

    1
        John.getOlder();

    5。

    1
        Person.prototype;

    您创建的每个函数都有一个名为prototype的属性,它作为一个空对象开始。在将此函数用作构造函数(即使用'new'关键字)之前,此属性无用。

    这通常与对象的__proto__属性混淆。有些人可能会感到困惑,除了对象的prototype属性可能会使它们成为对象的原型。但事实并非如此。 prototype用于获取从函数构造函数创建的对象的__proto__

    在上面的例子中:

    1
    2
    3
    4
    5
    6
    7
    8
    function Person(name){
        this.name = name
    };

    var eve = new Person("Eve");

    console.log(eve.__proto__ == Person.prototype) // true
    // this is exactly what prototype does, made Person.prototype equal to eve.__proto__

    我希望这是有道理的。


    使用__proto__进行静态方法怎么样?

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    function Foo(name){
      this.name = name
      Foo.__proto__.collection.push(this)
      Foo.__proto__.count++

    }

    Foo.__proto__.count=0
    Foo.__proto__.collection=[]

    var bar = new Foo('bar')
    var baz = new Foo('baz')

    Foo.count;//2
    Foo.collection // [{...}, {...}]
    bar.count // undefined


    1
    2
    3
    4
    5
    6
    7
    8
    (function(){
          let a = function(){console.log(this.b)};
          a.prototype.b = 1;
          a.__proto__.b = 2;
          let q = new a();
          console.log(a.b);
          console.log(q.b)
        })()

    试试这段代码吧


    解释性的例子:

    1
    2
    3
    4
    function Dog(){}
    Dog.prototype.bark ="woof"

    let myPuppie = new Dog()

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

    1
    2
    > myPuppie.__proto__
    >> {bark:"woof", constructor: ?}

    但myPuppie没有原型属性。

    1
    2
    > myPuppie.prototype
    >> undefined

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

    MPJ在这里做了很好的解释:
    proto vs prototype - JavaScript中的对象创建


    我会尝试四年级的解释:

    事情很简单。 prototype是应该如何构建某个东西的示例。所以:

    • 我是function,我构建了类似于我的prototype的新对象

    • 我是object,我使用__proto__作为示??例构建

    证明:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    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


    正如这正确地指出的那样

    __proto__ is the actual object that is used in the lookup chain to
    resolve methods, etc. prototype is the object that is used to build
    __proto__ when you create an object with new:

    1
    2
    ( new Foo ).__proto__ === Foo.prototype;
    ( new Foo ).prototype === undefined;

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

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

    请考虑以下示例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    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的基础和构造函数,例如:function human(){}具有prototype,它在构造函数的新实例中通过__proto__共享。这里有更详细的说明


    我的理解是:__ proto__和原型都是为原型链技术服务的。不同之处在于使用下划线命名的函数(如__proto__)并不是开发人员明确调用的目标。换句话说,它们只是用于继承等机制,它们是"后端"。但是没有下划线命名的函数是为明确调用而设计的,它们是'前端'。


    !!!这是世界上最好的解释!!!!!

    1
    2
    3
    4
    5
    6
    var q = {}
    var prototype = {prop: 11}

    q.prop // undefined
    q.__proto__ = prototype
    q.prop // 11

    在函数构造函数中,当我们编写new Class时,javascript引擎会自动调用此q.__proto__ = prototype,并进入__proto__ prop set Class.prototype

    1
    2
    3
    4
    5
    function Class(){}
    Class.prototype = {prop: 999} // set prototype as we need, before call new

    var q = new Class() // q.__proto__ = Class.prototype
    q.prop // 999

    请享用 %)