__proto__ VS. прототип в JavaScript - PullRequest
       85

__proto__ VS. прототип в JavaScript

707 голосов
/ 01 апреля 2012

Этот рисунок снова показывает, что у каждого объекта есть прототип. Конструктор Функция Foo также имеет свой собственный __proto__, который является Function.prototype, и который в свою очередь также ссылается через свойство __proto__ снова на Object.prototype. Таким образом, повторяю, Foo.prototype просто явный свойство Foo, которое относится к прототипу объектов b и c.

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

В чем различия между __proto__ и prototype свойствами?

enter image description here

Цифра взята из здесь .

Ответы [ 25 ]

691 голосов
/ 01 апреля 2012

__proto__ - это фактический объект, который используется в цепочке поиска для разрешения методов и т. Д. prototype - это объект, который используется для построения __proto__ при создании объекта с new:

( new Foo ).__proto__ === Foo.prototype;
( new Foo ).prototype === undefined;
312 голосов
/ 01 апреля 2012

prototype является свойством объекта Function.Это прототип объектов, созданных этой функцией.

__proto__ является внутренним свойством объекта, указывающим на его прототип.Текущие стандарты предоставляют эквивалентный метод Object.getPrototypeOf(O), хотя де-факто стандарт __proto__ быстрее.

Вы можете найти отношения instanceof, сравнив prototype функции с цепочкой __proto__ объекта, и выможно разорвать эти отношения, изменив 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.prototype сохраняется в myPoint.__proto__ в то время.

109 голосов
/ 10 августа 2013

Свойство прототипа создается при объявлении функции.

Например:

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

Свойство Person.prototype создается внутри, как только вы объявляете вышеуказанную функцию. Многие свойства могут быть добавлены в Person.prototype, которые совместно используются экземплярами Person, созданными с использованием new Person ().

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

Стоит отметить, что Person.prototype является литералом Object по умолчанию (его можно изменить при необходимости).

Каждый экземпляр, созданный с использованием new Person(), имеет свойство __proto__, которое указывает на Person.prototype. Это цепочка, которая используется для поиска свойства определенного объекта.

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

создает 2 экземпляра Person, эти 2 объекта могут вызывать age метод Person.prototype как person1.age, person2.age.

На приведенном выше рисунке из вашего вопроса вы можете видеть, что Foo - это Function Object, и поэтому он имеет __proto__ ссылку на Function.prototype, которая, в свою очередь, является экземпляром Object и имеет __proto__ ссылка на Object.prototype. Прото-ссылка заканчивается здесь __proto__ в Object.prototype, указывающим на null.

Любой объект может иметь доступ ко всем свойствам в своей цепочке прототипов, которые связаны __proto__, тем самым формируя основу для наследования прототипов.

__proto__ не является стандартным способом доступа к цепочке прототипов, стандартным, но похожим подходом является использование Object.getPrototypeOf(obj).

Ниже код оператора instanceof дает лучшее понимание:

объект instanceof Оператор класса возвращает true, когда объект является экземпляром класса, более конкретно, если в цепочке протоколов этого объекта обнаружен Class.prototype, тогда объект является экземпляром этого класса.

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), который возвращает true, если объект является экземпляром класса.

61 голосов
/ 30 мая 2014

Хороший способ думать об этом ...

prototype используется функциями constructor(). На самом деле это должно было называться что-то вроде "prototypeToInstall", поскольку это то, что есть.

и __proto__ - это тот «установленный прототип» на объекте (который был создан / установлен на объекте из указанной constructor() функции)

46 голосов
/ 02 февраля 2017

Чтобы объяснить, давайте создадим функцию

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

Когда JavaScript выполняет этот код, он добавляет свойство prototype к a, свойство prototype является объектом с двумя свойствами:

  1. constructor
  2. __proto__

Поэтому, когда мы делаем

a.prototype, возвращается

     constructor: a  // function definition
    __proto__: Object

Теперь, как вы можете видеть, constructor - это не что иное, как сама функция a и __proto__, указывающая на корневой уровень Object JavaScript.

Давайте посмотрим, что произойдет, когда мы используем a функция с new ключевым словом.

var b = new a ('JavaScript');

Когда JavaScript выполняет этот код, он выполняет 4 вещи:

  1. Создает новый объект, пустой объект // {}
  2. Создает __proto__ на b и указывает на a.prototype, поэтому b.__proto__ === a.prototype
  3. Он выполняет a.prototype.constructor (что является определением функции a) свновь созданный объект (созданный на шаге 1) как его контекст (this), следовательно, свойство name, переданное как 'JavaScript' (которое добавляется в this), добавляется во вновь созданный объектt.
  4. Возвращает вновь созданный объект (созданный на шаге # 1), поэтому var b назначается вновь созданному объекту.

Теперь, если мы добавим a.prototype.car = "BMW" иdo b.car, выводится «BMW».

это потому, что когда JavaScript выполнял этот код, он искал свойство car в b, он не нашел тогда используемый JavaScript b.__proto__ (которыйбыл создан для указания на «a.prototype» на шаге # 2) и находит свойство car, поэтому возвращает «BMW».

44 голосов
/ 23 сентября 2015

Прототип VS.__proto__ VS.[[Prototype]]

При создании функции объект свойства с именем prototype создается автоматически (вы не создавали его самостоятельно) и присоединяется к функцииобъект (constructor).
Примечание : Этот новый объект прототип также указывает или имеет внутренне-частную ссылку на собственный объект JavaScript.

Пример:

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;
}

Если вы создадите новый объект из Foo с помощью ключевого слова new, вы в основном создаете (среди прочего) новый объект, имеющий внутренняя или приватная ссылка на прототип функции Foo, который мы обсуждали ранее:

var b = new Foo();

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


приватная связь с объектом этой функции, называемая прототипом в двойных скобках или просто [[Prototype]].Многие браузеры предоставляют нам общедоступную ссылку на нее, которая называется __proto__!

Точнее говоря, __proto__ на самом деле является функцией получения , которая принадлежитнативный объект JavaScript.Он возвращает внутренне-частную связь прототипа с любой привязкой this (возвращает [[Prototype]] из b):

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

Стоит отметить, что начиная с ECMAScript5, вы можететакже используйте метод getPrototypeOf для получения внутренней частной связи:

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


ПРИМЕЧАНИЕ. этот ответ не предназначен для охвата всего процессасоздание новых объектов или новых конструкторов, но чтобы лучше понять, что такое __proto__, prototype и [[Prototype]] и как это работает.
28 голосов
/ 07 октября 2015

Чтобы сделать это немного яснее в дополнение к вышеупомянутым великолепным ответам:

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

var eve = new Person("Eve");

eve.__proto__ == Person.prototype //true

eve.prototype  //undefined

Экземпляры имеют __ proto __ , классы имеют прототип .

10 голосов
/ 27 декабря 2016

В JavaScript функцию можно использовать как конструктор. Это означает, что мы можем создавать объекты из них, используя ключевое слово new. Каждая функция конструктора имеет встроенный объект, связанный с ними. Этот встроенный объект называется прототипом. Instances of a constructor function use __proto__ to access the prototype property of its constructor function.

prototype diagram

  1. Сначала мы создали конструктор: function Foo(){}. Чтобы быть понятным, Foo это просто еще одна функция. Но мы можем создать объект из него с новым ключевым словом. Вот почему мы называем это функцией конструктора

  2. Каждая функция имеет уникальное свойство, которое называется свойством прототипа. Итак, функция Constructor Foo имеет свойство prototype, которое указывает на его прототип, который равен Foo.prototype (см. Изображение).

  3. Функции-конструкторы сами являются функцией, которая является экземпляром системного конструктора, называемого конструктором [[Function]]. Таким образом, мы можем сказать, что function Foo создается конструктором [[Function]]. Таким образом, __proto__ нашего Foo function будет указывать на прототип его конструктора, который равен Function.prototype.

  4. Function.prototype сам по себе является ничем иным, как объектом, созданным из другого системного конструктора с именем [[Object]]. Итак, [[Object]] является конструктором Function.prototype. Таким образом, мы можем сказать, что Function.prototype является экземпляром [[Object]]. Так __proto__ из Function.prototype указывает на Object.prototype.

  5. Object.prototype - последний человек, стоящий в цепи прототипов. Я имею в виду это не было построено. Это уже есть в системе. Так что __proto__ указывает на null.

  6. Теперь мы подошли к случаям Foo. Когда мы создаем экземпляр, используя new Foo(), он создает новый объект, который является экземпляром Foo. Это означает, что Foo является конструктором этих экземпляров. Здесь мы создали два экземпляра (x и y). __proto__ из x и y, таким образом, указывает на Foo.prototype.

7 голосов
/ 03 июля 2017

Я изучаю прототип из Вы не знаете JS: этот & Прототипы объектов , замечательная книга, чтобы понять дизайн под ним и прояснить так много заблуждений (вот почему я пытаюсьизбегать использования наследования и тому подобных instanceof).

Но у меня тот же вопрос, что и здесь.Несколько ответов действительно полезны и поучительны.Я также хотел бы поделиться своим пониманием.


Что такое прототип?

У объектов в JavaScript есть внутреннее свойство, обозначенное в спецификации как [[Prototype]], которое просто является ссылкой на другой объект.Почти всем объектам присваивается значение, не равное null, для этого свойства во время их создания.

Как получить прототип объекта?

через __proto__ или Object.getPrototypeOf

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 и сохраняет код функции как constructorprototype.

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

Я хотел бы рассмотреть это свойство как место для хранения свойств (включая методы) функционального объекта.Это также причина, по которой служебные функции в JS определяются как Array.prototype.forEach(), Function.prototype.bind(), Object.prototype.toString().

Зачем подчеркивать свойство функции ?

{}.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();

Итак, Arary, Function, Object - все функции.Я должен признать, что это освежает мое впечатление о JS.Я знаю, что функции в JS являются первоклассным гражданином, но похоже, что он построен на функциях.

В чем разница между __proto__ и prototype?

__proto__ справочник работаетна каждый объект для ссылки на его свойство [[Prototype]].

prototype - это объект, автоматически создаваемый как специальное свойство функции , которая используется дляхранить свойства (включая методы) функционального объекта.

С этими двумя мы можем мысленно отобразить цепочку прототипов.Как показано на рисунке:

function Foo() {}
var b = new Foo();

b.__proto__ === Foo.prototype // true
Foo.__proto__ === Function.prototype // true
Function.prototype.__proto__ === Object.prototype // true
6 голосов
/ 12 мая 2015

Еще один хороший способ понять это:

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__.

...