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

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

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

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

введите описание изображения здесь

Рисунок взят с сайта dmitrysoshnikov.com.


person 0x90    schedule 31.03.2012    source источник
comment
См. Также Чем __proto__ отличается от constructor.prototype?   -  person Bergi    schedule 15.03.2014
comment
Я думаю, что предпочтение будет отдаваться сверху вниз или снизу вверх. На самом деле я предпочитаю этот способ, поэтому я могу проследить диаграмму, пока не найду, откуда что-то взялось.   -  person Mike Lippert    schedule 16.08.2014
comment
Мне нравится, как JavaScript использует прототипное наследование для преобразования y.constructor в y .__ proto __. Constructor. Мне также нравится, как Object.prototype находится в верхней части прототипной цепочки наследования с Object.prototype .__ proto__, установленным в значение null. Мне также нравится, как диаграмма представляет собой трехколоночную концептуальную визуализацию того, как программист думает об объектах как 1. экземплярах, 2. конструкторах, 3. прототипах, которые конструкторы связывают с этими экземплярами при создании экземпляров с помощью ключевого слова new.   -  person John Sonderson    schedule 30.10.2014
comment
Диаграмма становится понятной сразу после того, как вы посмотрите что-то вроде youtube.com/watch?v=_JJgSbuj5VI. , Кстати   -  person mlvljr    schedule 09.02.2015
comment
И теперь, когда я прочитал ответы, чувствую себя обязанным действительно порекомендовать вышеупомянутое видео, поскольку в нем действительно есть кристально чистое (и не WTFy) объяснение того, что происходит :)   -  person mlvljr    schedule 09.02.2015


Ответы (31)


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

( new Foo ).__proto__ === Foo.prototype;
( new Foo ).prototype === undefined;
person Mark Kahn    schedule 31.03.2012
comment
Ах! Таким образом, prototype недоступен для самих экземпляров (или других объектов), а только для функций-конструкторов. - person rvighne; 06.08.2014
comment
@rvighne: prototype доступен только для функций, поскольку они являются производными от Function, Function и Object, но во всех остальных случаях это не так. Однако __proto__ доступен везде. - person Tarik; 27.09.2014
comment
Итак, __proto__ - это фактический объект, который сохраняется и используется в качестве прототипа, а Myconstructure.prototype - это просто план для __proto__, который фактически является фактическим объектом, сохраненным и используемым в качестве прототипа. Следовательно, myobject.prototype не будет свойством фактического объекта, потому что это всего лишь временная вещь, используемая функцией-конструктором для определения того, как должен выглядеть myobject.__proto__. - person Alex_Nabu; 29.07.2015
comment
Вероятно, одна из тех вещей, встроенных в язык, когда он пытался имитировать классический oop. Если бы это было не так, мы, возможно, вместо этого увидели бы нечто большее, похожее на var mycar = Object.Createfrom(car.__proto__);, при создании объектов. Более верен прототипическому стилю программирования. - person Alex_Nabu; 29.07.2015
comment
Можно ли сказать, что свойство __proto__ объекта является указателем на свойство prototype функции конструктора объекта? т.е. foo .__ proto__ === foo.constructor.prototype - person Niko Bellic; 19.08.2015
comment
@Alex_Nabu Не совсем так. newCar.__proto__ IS Car.prototype, а не экземпляр Car.prototype. Хотя Car.protoype ЯВЛЯЕТСЯ экземпляром object. Car.prototype не является чем-то, что дает newCar какие-либо свойства или структуру, это просто ЕСТЬ следующий object в цепочке прототипов newCar. Car.prototype не является временным object. Это object, который устанавливается как значение свойства __proto__ для любых новых object, созданных с использованием Car в качестве constructor. Если вы хотите думать о чем-либо как о проекте object, думайте о Car как о проекте нового автомобиля-object. - person seangwright; 10.02.2016
comment
Почему я не могу заменить, например, __proto__ строки на экземпляр массива: s = "foo"; a = []; s.__proto__ = a;? - person Mikhail Batcer; 29.04.2016
comment
@MikhailBatcer - Примитивы в JS - это особый случай. Всякий раз, когда вы обращаетесь к ним, они эффективно преобразуются в экземпляр соответствующего типа класса, а затем на нем выполняются операции. Итак, после кода, который вы написали, s.__proto__ - это что-то близкое к (new String(s)).__proto__. Если вы замените свой первый оператор на s = new String('foo'), он сработает. Это просто странная причуда в JS - person Mark Kahn; 29.04.2016
comment
@Niko Bellic Попался! Справедливо сказать, что свойство proto объекта является указателем на свойство прототипа функции конструктора объекта, но это не совсем верно (по крайней мере, если вы замените прототип не родного конструктора примитивным значением. literal ie: '' || 0 || true afaik)! Я тестировал это в Chrome, и он вернул что-то другое: function MyConstructor () {} MyConstructor.prototype = ''; (new MyConstructor).__proto__ !== MyConstructor.prototype. Я думаю, что браузер не может создать proto с примитивным литералом, создав его с помощью Object.prototype - person Daniel; 05.10.2016
comment
@Niko Bellic На самом деле он не создает его и с помощью Object.prototype, мне, возможно, придется немного взглянуть на это, чтобы дать более точный ответ! Однако (new MyConstructor).__proto__ на самом деле то же самое, что (new MyConstructor).constructor.prototype! - person Daniel; 05.10.2016
comment
@Daniel - Есть так много способов взломать JavaScript, но, честно говоря, я не вижу смысла обсуждать крайние случаи, в которые ни один здравомыслящий человек никогда не попадет! :) - person Mark Kahn; 06.10.2016
comment
Это лучший ответ, который я когда-либо видел. Действительно по делу, без суеты. - person mplwork; 13.01.2020

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

__proto__ - это внутреннее свойство объекта, указывающее на его прототип. Текущие стандарты предоставляют эквивалентный Object.getPrototypeOf(obj) метод, хотя стандарт де-факто __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__.

person Imp    schedule 31.03.2012
comment
Кроме того, если вы измените свойство __proto__ объекта, это изменит объект, для которого выполняется поиск прототипа. Например, вы можете добавить объект методов как __proto__ функции, чтобы иметь своего рода вызываемый объект-экземпляр. - person kzh; 19.08.2014
comment
myPoint .__ proto __. constructor.prototype == Point.prototype - person Francisco; 21.03.2016
comment
@kzh lol, который дал мне забавный результат console.log(obj1.call) // [Function: call] obj1.call() // Ошибка типа: obj1.call не является функцией. Я сделал obj.__proto__ = Function.__proto__ - person abhisekp; 01.07.2016
comment
Думаю, я понял вашу точку зрения. - person ComicScrip; 26.11.2019

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

Например:

 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 дает лучшее понимание:

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

person sid_k_reddy    schedule 10.08.2013
comment
Мне было интересно, почему объект prototype был создан внутри компании? Можно ли просто назначить статические методы самому объекту функции. например function f(a){this.a = a}; f.increment = function(){return ++this.a}? Почему не был выбран этот способ вместо добавления методов к объекту prototype? Это будет работать, если f.__proto__ = g где g - базовый класс. - person abhisekp; 01.07.2016
comment
Возможно, объект prototype был выбран для совместного использования, потому что в объекте конструктора функции могут храниться только эксклюзивные свойства конструктора функции. - person abhisekp; 01.07.2016
comment
На самом деле, это будет беспорядок, потому что instanceof приведет к ({}) instanceof Function === true, поскольку не будет возможности различать прототипы, если свойство prototype будет удалено. - person abhisekp; 01.07.2016
comment
@abhisekp Что вы имеете в виду: это будет работать, если f .__ proto__ = g, где g - базовый класс. Я не знаю, имеет ли это какое-то значение, которое я не понимаю, но если бы вы добавили свойства и методы таким образом, тогда, когда вы использовали бы ключевое слово new для создания экземпляра, свойства и методы не были бы скопировано. - person doubleOrt; 08.09.2017

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

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

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

person sarink    schedule 30.05.2014
comment
Я поддержал его, но, возможно, причина отрицательного ответа заключалась в том, что прототип оператора используется функциями constructor () может звучать так, как будто функции, не являющиеся конструкторами, не имеют, что не так, однако, помимо того, что это не наш фокус, теперь также можно обратите внимание, что каждая функция потенциально является конструктором, если вызывается с помощью new ... - person yoel halb; 02.02.2015
comment
Измените constructor() функции на функции-конструкторы, поскольку может возникнуть путаница с __proto__.constructor() функциями. Я считаю это важным, поскольку конструктор __proto __. Фактически не вызывается при использовании ключевого слова new. - person Alexander Gonchiy; 08.08.2015
comment
Утверждение, что prototype используется функциями constructor (), сообщает только часть важного факта, но сообщает его таким образом, чтобы читатели могли подумать, что это весь факт. прототип создается внутри для каждого объявления функции в Javascript, независимо от того, как эта функция будет вызываться в будущем - с ключевым словом new или без него; прототип объявленной функции указывает на литерал объекта. - person Yiling; 02.05.2016

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

 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), добавляется к вновь созданному объекту. созданный объект.
  4. Он возвращает вновь созданный объект в (созданный на шаге № 1), поэтому var b назначается вновь созданному объекту.

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

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

person Manishz90    schedule 02.02.2017
comment
1. constructor не возвращает a()! Возвращает a. 2. __proto__ возвращает Object.prototype, а не корневой объект в Javascript. - person doubleOrt; 08.09.2017
comment
Это отличный ответ! - person john-raymon; 22.06.2019
comment
+1 это лучший ответ для объяснения того, какой прототип на самом деле ЕСТЬ (объект с двумя свойствами) и как Javascript выполняет каждый фрагмент кода. Эту информацию на удивление сложно найти. - person java-addict301; 06.05.2020

Прототип 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]] и как это работает.

person Lior Elrom    schedule 23.09.2015
comment
@Taurus, щелкните заголовок, откроется документ спецификаций ECMAScript. Ознакомьтесь с разделом 9 (Поведение обычных и экзотических объектов), в котором это объясняется более подробно. - person Lior Elrom; 08.09.2017

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

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

var eve = new Person("Eve");

eve.__proto__ == Person.prototype //true

eve.prototype  //undefined

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

person serkan    schedule 07.10.2015
comment
Функции и классы-конструкторы также имеют свойство __proto__, оно не зарезервировано для экземпляров. Функции и классы-конструкторы имеют свойство __proto__, а также свойство prototype. См. stackoverflow.com/a/42002749/1347953 - person Sébastien; 29.12.2020
comment
Коротко и мило - person Vigneshwaran Chandrasekaran; 16.06.2021

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

схема прототипа

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

  2. Каждая функция имеет уникальное свойство, которое называется свойством прототипа. Итак, функция конструктора Foo имеет свойство прототипа, которое указывает на ее прототип, которым является 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__ of x и y, таким образом, указывает на Foo.prototype.

person AL-zami    schedule 27.12.2016
comment
Чтобы быть ясным: у экземпляров нет свойства .prototype? Только функция конструктора, верно? ... Итак, разница между экземпляром и его функцией-конструктором заключается в следующем: функции-конструкторы имеют оба объекта: 1. proto 2. .prototype, в то время как экземпляры имеют только свойство .__ proto__ ... правильно? - person Shaz; 15.01.2019
comment
@Shaz, ты прав. экземпляры используют свой proto для доступа к свойству прототипа своей функции-конструктора. - person AL-zami; 15.01.2019
comment
Но почему, когда вы пишете: var car = Object.create (Vehicle); вы получите car .__ proto__ = Vehicle, НО вы также получите свойство car.prototype, которое указывает на Vehicle.prototype? - person Shaz; 15.01.2019
comment
@shaz, можете ли вы предоставить jsfiddle, чтобы я мог визуализировать ситуацию? - person AL-zami; 15.01.2019
comment
jsfiddle.net/shahyan3/b5tr3zhk/6 Вот это ... посмотрите машину и car2 в качестве примеров. Любые идеи? - person Shaz; 15.01.2019
comment
здесь car.prototype - это унаследованное свойство. car наследует свойство prototype от функции транспортного средства. итак car.prototype === vehicle.prototype. Свойство прототипа - это собственность на транспортном средстве. автомобиль может получить к нему доступ через свою цепочку прототипов. Надеюсь, это прояснит ваше замешательство - person AL-zami; 15.01.2019
comment
О, я вижу. Вы новичок в мире JavaScript, ваш ответ очень хорош. Быстро, это обычная практика - писать: Object.create (Vehicle) OR Object.create (Vehicle.prototype) ... Я предполагаю, что последнее является более популярным вариантом использования - по вашему опыту? - person Shaz; 15.01.2019

Резюме:

Свойство __proto__ объекта - это свойство, которое отображается на prototype функции конструктора объекта. Другими словами:

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

Это используется для формирования цепочки prototype объекта. Цепочка prototype - это механизм поиска свойств объекта. Если осуществляется доступ к свойству объекта, JavaScript сначала просматривает сам объект. Если свойство там не найдено, оно будет подниматься до protochain, пока не будет найдено (или не найдено)

Пример:

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 функции также являются объектами. Объекты могут иметь свойства, и свойство по умолчанию любой функции - это одно свойство с именем прототип.

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

Почему это полезно?

В JavaScript есть механизм поиска свойств на Objects, который называется «прототипное наследование», вот что он в основном делает:

  • Сначала проверяется, находится ли свойство на самом объекте. Если да, возвращается это свойство.
  • Если свойство не находится на самом объекте, оно будет «взбираться вверх по протоцепи». В основном он смотрит на объект, на который указывает свойство __proto__. Там он проверяет, доступно ли свойство для объекта, на который ссылается __proto__.
  • Если свойство не находится на объекте __proto__, оно поднимется вверх по цепочке __proto__ вплоть до объекта Object.
  • Если он не может найти свойство где-либо в объекте и его цепочке prototype, он вернет undefined.

Например:

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

let mySelf = new Person('Willem');

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

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

person Willem van der Veen    schedule 17.08.2018

Я изучаю прототип из You Don't Know JS: this & Object Prototypes, замечательная книга, которая помогает понять суть дизайна и прояснить многие заблуждения (вот почему я стараюсь избегать использования наследования и подобных вещей 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 и сохраняет код функции как constructor на prototype.

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
person ifyouseewendy    schedule 02.07.2017

Прототип JavaScript против __prototype__

'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__, свойство конструктора prototype - работа с оператором new.

Конструктор должен быть функцией, но функция не всегда является конструктором, даже если у нее есть свойство prototype.

Цепочка прототипов на самом деле является свойством __proto__ объекта для ссылки на его прототип, и свойством __proto__ прототипа для ссылки на прототип прототипа и так далее, пока не будет указано свойство прототипа объекта __proto__, которое ссылается на null.

Например:

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, чтобы получить прототип чего-то.

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

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

person 林奕忠    schedule 05.08.2018

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

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

person Yad Smood    schedule 12.05.2015
comment
Только то, что я бы написал наоборот: foo .__ proto__ === foo.constructor.prototype - person epeleg; 08.11.2015

прототип

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

__proto__

__proto__ используется в поисковой цепочке для разрешения методов и свойств. когда объект создается (с использованием функции конструктора с новым ключевым словом), __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 / coockie 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;
    }

} 

Итак,

var robot = new Robot();

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

Теперь добавляем метод в prototype робота:

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
    };
}
person Hassan Tareq    schedule 14.09.2017
comment
все еще думаю о более последовательных именах для __proto__ и прототипа. может прототип и наследование? - person Dmitry; 02.04.2018
comment
Я бы сказал, prototype и __proto__ следует избегать обоих. У нас сейчас класс, и мне нравится ООП. - person Hassan Tareq; 02.04.2018
comment
проблема в том, что класс относительно новый и не поддерживается действительно удобными движками, такими как Microsoft JScript (приятно иметь при работе на C и нужен быстрый и грязный скриптовый движок, который всегда есть) и javascript nashorn (который поставляется со всеми новые установки Java под jjs и это хороший способ поместить Java в чисто динамическую среду, где вам не нужно постоянно перекомпилировать вещи). Дело в том, что если бы класс был сахаром, это не было бы проблемой, но это не так, он предлагает вещи, которые невозможны без них в более старых версиях js. Как расширение Function. - person Dmitry; 02.04.2018
comment
Со временем мы получим поддержку. Я backend-разработчик, поэтому проблем у меня нет, на js кодирую редко. - person Hassan Tareq; 02.04.2018
comment
и наследование статических членов таким образом, чтобы добавление новых / удаление статических членов из родительского элемента было замечено дочерним элементом (что я не могу придумать, как сделать это в JScript, который не предлагает Object.assign / __ proto __ / getPrototypeOf, поэтому вы придется повозиться с корневым Object.prototype, чтобы смоделировать его) - person Dmitry; 02.04.2018

Проще говоря:

> var a = 1
undefined
> a.__proto__
[Number: 0]
> Number.prototype
[Number: 0]
> Number.prototype === a.__proto__
true

Это позволяет вам прикреплять свойства к X.prototype ПОСЛЕ того, как объекты типа X были созданы, и они по-прежнему будут получать доступ к этим новым свойствам через ссылку __proto__, которую Javascript-движок использует для перехода по цепочке прототипов.

person Andreas Bergström    schedule 24.10.2015

Prototype или Object.prototype - это свойство литерала объекта. Он представляет собой объект-прототип Object, который можно переопределить, чтобы добавить дополнительные свойства или методы дальше по цепочке прототипов.

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

Ссылки:

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

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

person akodevs    schedule 19.11.2015
comment
Object.prototype не является свойством литерала объекта, попытка распечатать {}.prototype возвращает значение undefined; однако к нему можно получить доступ через {}.__proto__, который возвращает Object.prototype. - person doubleOrt; 08.09.2017

Я сделал для себя небольшой рисунок, представляющий следующий фрагмент кода:

var Cat = function() {}
var tom = new Cat()

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

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

У объектов в JavaScript есть свойства, и __proto__ - лишь одно из них.

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

Корневой объект в JavaScript - это Object.prototype, а все остальные объекты являются его потомками. Свойство __proto__ корневого объекта - null, которое представляет конец цепочки наследования.

Вы заметите, что prototype - это свойство функций. Cat - это функция, но также Function и Object (собственные) функции. tom не является функцией, поэтому у него нет этого свойства.

Идея этого свойства состоит в том, чтобы указать на объект, который будет использоваться в конструкции, т.е. когда вы вызываете оператор new для этой функции.

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

Действительно, когда мы создаем объект tom с new Cat(), для созданного объекта будет установлено свойство __proto__, равное объекту prototype функции-конструктора.

В конце концов, давайте немного поиграем с этой диаграммой. Верны следующие утверждения:

  • tom.__proto__ указывает на тот же объект, что и Cat.prototype.

  • Cat.__proto__ указывает на объект Function.prototype, точно так же, как Function.__proto__ и Object.__proto__.

  • Cat.prototype.__proto__ и tom.__proto__.__proto__ указывают на один и тот же объект, и это Object.prototype.

Ваше здоровье!

person theshinylight    schedule 26.11.2019
comment
Очень хорошо объяснено! - person StackOverflow UI; 23.12.2019
comment
@theshinylight, tom.__proto__ и Cat.prototype строго равны, поэтому tom.__proto__ === Cat.prototype и Cat.prototype === tom.__proto__ верны. Итак, что вы имели в виду под стрелкой на картинке ?? - person aeXuser264; 20.01.2020
comment
Черная стрелка (если вы имеете в виду ее) не имеет особого значения, кроме свойства объекта. Итак, prototype является свойством объекта Cat (из вашего вопроса). - person theshinylight; 21.01.2020
comment
Блестящее объяснение - person seeker; 11.08.2020

Я знаю, я опаздываю, но позвольте мне попытаться упростить.

Допустим, есть функция

    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);
  1. Теперь у нас есть два объекта: объект a и объект b. Оба созданы с помощью конструктора Foo. Имейте в виду, что конструктор - это просто слово.
  2. Оба объекта a и b имеют копию свойства сообщения.
  3. Эти два объекта a и b связаны с объектом-прототипом конструктора Foo.
  4. На объектах a и b мы можем получить доступ к прототипу Foo, используя свойство __proto__ во всех браузерах, а в 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__;

все вышеперечисленное вернет истину.

Как известно, в JavaScript свойства можно добавлять динамически. Мы можем добавить свойство к объекту

    Foo.prototype.Greet = function(){

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

Как видите, мы добавили метод Greet () в Foo.prototype, но он доступен в a и b или в любом другом объекте, созданном с использованием Foo.

При выполнении a.Greet () JavaScript сначала выполняет поиск Greet в объекте a в списке свойств. Не найдя, он поднимется в цепочке __proto__ файла. Поскольку .__ proto__ и Foo.prototype - это один и тот же объект, JavaScript найдет метод Greet () и выполнит его.

Надеюсь, теперь прототип и __proto__ немного упростились.

person debugmode    schedule 23.09.2016

Пояснительный пример:

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

let myPuppie = new Dog()

теперь myPupppie имеет свойство __proto__, которое указывает на Dog.prototype.

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

но myPuppie НЕ имеет свойства прототипа.

> myPuppie.prototype
>> undefined

Итак, __proto__ mypuppie - это ссылка на свойство .prototype функции-конструктора, которое использовалось для создания экземпляра этого объекта (и текущий объект myPuppie имеет отношение «делегаты» к этому объекту __proto__), а. Свойство prototype у myPuppie просто отсутствует (поскольку мы его не задавали).

Хорошее объяснение MPJ здесь: прототип против объекта Создание в JavaScript

person Nitin Jadhav    schedule 16.12.2018

[[Прототип]]:

[[Prototype]] - это внутреннее скрытое свойство объектов в JS и ссылка на другой объект. Каждый объект во время создания получает ненулевое значение для [[Prototype]]. Помните, что операция [[Get]] вызывается, когда мы ссылаемся на свойство объекта, например myObject.a. Если у самого объекта есть свойство a, то будет использовано это свойство.

let myObject= {
    a: 2
};

console.log(myObject.a);            // 2

Но если сам объект напрямую не имеет запрошенного свойства, тогда операция [[Get]] перейдет по ссылке [[Prototype]] объекта. Этот процесс будет продолжаться до тех пор, пока не будет найдено подходящее имя свойства или пока не завершится цепочка [[Prototype]] (во встроенном Object.prototype). Если подходящего свойства не найдено, будет возвращено значение undefined. Object.create (specifiedObject) создает объект со связью [[Prototype]] с указанным объектом.

let anotherObject= {
    a: 2
};

// create an object linked to anotherObject
let myObject= Object.create(anotherObject);
console.log(myObject.a);                // 2

Как цикл for..in, так и оператор in используют процесс поиска в цепочке [[Prototype]]. Итак, если мы используем цикл for..in для перебора свойств объекта, тогда все перечисляемые свойства, которые могут быть достигнуты через цепочку [[Prototype]] этого объекта, также будут перечислены вместе с перечисляемыми свойствами самого объекта. А при использовании оператора in для проверки наличия свойства у объекта оператор in будет проверять все свойства через связь [[Prototype]] объекта независимо от их перечислимости.

// for..in loop uses [[Prototype]] chain lookup process
let anotherObject= {
    a: 2
};

let myObject= Object.create(anotherObject);

for(let k in myObject) {
    console.log("found: " + k);            // found: a
}

// in operator uses [[Prototype]] chain lookup process
console.log("a" in myObject);              // true

.prototype:

.prototype - это свойство функций в JS и относится к объекту, имеющему свойство конструктора, в котором хранятся все свойства (и методы) объекта функции.

let foo= function(){}

console.log(foo.prototype);        
// returns {constructor: f} object which now contains all the default properties

foo.id= "Walter White";

foo.job= "teacher";

console.log(foo.prototype);       
// returns {constructor: f} object which now contains all the default properties and 2 more properties that we added to the fn object
/*
{constructor: f}
    constructor: f()
        id: "Walter White"
        job: "teacher"
        arguments: null
        caller: null
        length: 0
        name: "foo"
        prototype: {constructor: f}
        __proto__: f()
        [[FunctionLocation]]: VM789:1
        [[Scopes]]: Scopes[2]
    __proto__: Object

*/

Но обычные объекты в JS не имеют свойства .prototype. Мы знаем, что Object.prototype является корневым объектом всех объектов в JS. Итак, очевидно, что Object - это функция, то есть typeof Object === function. Это означает, что мы также можем создать объект из функции Object, например let myObj = new Object (). Точно так же Array, Function также являются функциями, поэтому мы можем использовать Array.prototype, Function.prototype для хранения всех общих свойств массивов и функций. Итак, мы можем сказать, что JS построен на функциях.

{}.prototype;                            // SyntaxError: Unexpected token '.'

(function(){}).prototype;                // {constructor: f}

Также с помощью оператора new, если мы создаем объекты из функции, тогда внутреннее свойство hidden [[Prototype]] этих вновь созданных объектов будет указывать на объект, на который ссылается свойство .prototype исходной функции. В приведенном ниже коде мы создали объект a из fn, Letter и добавили 2 свойства: одно к объекту fn, а другое к объекту-прототипу fn. Теперь, если мы попытаемся получить доступ к обоим свойствам вновь созданного объекта, тогда мы сможем получить доступ только к свойству, добавленному к объекту-прототипу функции. Это связано с тем, что объект-прототип функции теперь находится в цепочке [[Prototype]] вновь созданного объекта, a.

let Letter= function(){}

let a= new Letter();

Letter.from= "Albuquerque";

Letter.prototype.to= "New Hampshire";

console.log(a.from);                // undefined

console.log(a.to);                  // New Hampshire

.__proto__:

.__proto__ - это свойство объектов в JS, и оно ссылается на другой объект в цепочке [[Prototype]]. Мы знаем, что [[Prototype]] - это внутреннее скрытое свойство объектов в JS, и оно ссылается на другой объект в цепочке [[Prototype]]. Мы можем получить или установить объект, на который ссылается внутреннее свойство [[Prototype]], двумя способами.

  1. Object.getPrototypeOf(obj) / Object.setPrototypeOf(obj)

  2. obj.__proto__

Мы можем пройти по цепочке [[Prototype]], используя: .__proto__.__proto__. .. Наряду с .constructor, .toString (), .isPrototypeOf () наше ужасное свойство proto (__proto__) фактически существует во встроенном корневом объекте Object.prototype, но доступно для любого конкретного объекта. Наш .__proto__ на самом деле является геттером / сеттером. Реализация .__proto__ в Object.prototype приведена ниже:

Object.defineProperty(Object.prototype, "__proto__", {
    get: function() {
        return Object.getPrototypeOf(this);
    },
    set: function(o) {
        Object.setPrototypeOf(this, o);
        return o;
    }
});

Получение значения obj.__proto__ похоже на вызов obj.__proto__(), который фактически возвращает вызов метода получения fn, Object.getPrototypeOf(obj), который существует в объекте Object.prototype. Хотя .__proto__ является настраиваемым свойством, мы не должны изменять [[Prototype]] уже существующего объекта из-за проблем с производительностью.

Используя оператор new, если мы создаем объекты из функции, тогда внутреннее свойство hidden [[Prototype]] этих вновь созданных объектов будет указывать на объект, на который ссылается свойство .prototype исходной функции. Используя свойство .__proto__, мы можем получить доступ к другому объекту, на который ссылается внутреннее скрытое свойство [[Prototype]] объекта. Но __proto__ - это не то же самое, что [[Prototype]], а скорее геттер / сеттер для него. Рассмотрим код ниже:

let Letter= function() {}

let a= new Letter();

let b= new Letter();

let z= new Letter();

// output in console
a.__proto__ === Letter.prototype;               // true

b.__proto__ === Letter.prototype;               // true

z.__proto__ === Letter.prototype;               // true

Letter.__proto__ === Function.prototype;        // true

Function.prototype.__proto__ === Object.prototype;        // true

Letter.prototype.__proto__ === Object.prototype;          // true

введите описание изображения здесь

person djbtalk    schedule 19.07.2020

Думаю, вам нужно знать разницу между __proto__, [[prototype]] и прототипом.

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

Чтобы быть более точным: __proto__ существует для КАЖДОГО объекта.

  • Но что такое вообще __proto__?

    • Well, it is an object referencing another object which is also a property of all objects, called [[prototype]].
    • Стоит отметить, что [[prototype]] - это то, что JavaScript обрабатывает внутри и недоступно для разработчика.
  • Зачем нам нужен объект ссылки на свойство [[prototype]] (всех объектов)?

    • 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.
  • Что же тогда prototype?

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

    • JavaScript использует prototype родительской функции для установки [[prototype]] дочерних функций, когда эта родительская функция запускается с new (помните, мы сказали, что все объекты имеют [[prototype]]? Ну, функции тоже являются объектами, поэтому они также имеют [[prototype]] ). Итак, когда [[prototype]] функции (дочернего элемента) установлен на prototype другой функции (родительского элемента), в итоге вы получите следующее:

      let child = new Parent();
      child.__proto__ === Parent.prototype // --> true.
      

      (Помните, что child.[[prototype]] недоступен, поэтому мы проверили его с помощью __proto__.)


Примечание 1: всякий раз, когда свойство не находится в дочернем элементе, __proto__ поиск будет выполняться неявно. Так, например, если child.myprop возвращает значение, вы не можете сказать, было ли myprop свойством дочернего элемента или одного из прототипов его родителей. Это также означает, что вам никогда не нужно делать что-то вроде: child.__proto__.__proto__.myprop самостоятельно, просто child.myprop сделает это автоматически.

Примечание 2. Даже если в родительском прототипе есть элементы, собственный prototype дочернего элемента изначально будет пустым объектом. Вы можете добавлять к нему элементы или удалять из него вручную, если хотите еще больше расширить цепочку наследования (добавить дочернего [ren] к дочернему). Или им можно манипулировать неявно, например, используя синтаксис класса .)

Примечание 3 __proto__ - это немного устарело, и современный JavaScript предлагает вместо этого использовать Object.setPrototypeOf и Object.getPrototypeOf.)

person aderchox    schedule 15.05.2021

ОПРЕДЕЛЕНИЯ

(число в скобках () - это «ссылка» на код, который написан ниже)

prototype - объект, который состоит из:
=> функций (3) этого конкретного ConstructorFunction.prototype (5), которые доступны каждому объекту (4), созданному или подлежащему созданию через этот конструктор функция (1)
=> сама функция-конструктор (1)
=> __proto__ этого конкретного объекта (объекта-прототипа)

__proto__ (dandor proto?) - ссылка МЕЖДУ любым объектом (2), созданным с помощью конкретной функции конструктора (1), И свойствами объекта-прототипа (5) этого конструктора, КОТОРЫЕ позволяют каждому созданному объекту (2 ), чтобы иметь доступ к функциям и методам прототипа (4) (__proto__ по умолчанию включен в каждый отдельный объект в JS)

УТОЧНЕНИЕ КОДА

1.

    function Person (name, age) {
        this.name = name;
        this.age = age;  

    } 

2.

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

3.

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

4.

    John.getOlder();

5.

    Person.prototype;
person Eduard    schedule 15.06.2017

Я попробую объяснение для 4-го класса:

Все очень просто. prototype - это пример того, как что-то должно быть построено. Так:

  • Я function и создаю новые объекты, похожие на мой prototype

  • Я object, и я был построен на моем __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
person vladCovaliov    schedule 12.01.2017
comment
Нет, ни prototype, ни __proto__ не используются в любое время в качестве чертежа для создания какого-либо объекта. Это миф, связанный с расплывчатым синтаксисом class и его предшественниками. Как говорится в сообщении с ответом, он просто используется для поисковой цепочки и в случае prototype для идентификации constructor, используемого с new (который является частью этого притворного классного механизма, который сбивает с толку многих пользователей, включая меня). - person Christof Kälin; 12.02.2017
comment
Во-первых, я должен быть функцией, и я создаю новые объекты, которые будут делегировать моему прототипу. - person Nitin Jadhav; 16.12.2018

Каждая создаваемая вами функция имеет свойство prototype и начинает свою жизнь как пустой объект. Это свойство бесполезно, пока вы не используете эту функцию как функцию-конструктор, то есть с ключевым словом 'new'.

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

В приведенном выше примере:

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__

Надеюсь, это имеет смысл.

person Malkeet Singh    schedule 05.04.2017
comment
prototype не используется для создания __proto__ объекта. __proto__ при доступе просто предоставляет ссылку на объект prototype. - person doubleOrt; 08.09.2017

А как насчет использования __proto__ для статических методов?

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
person Barrard    schedule 29.03.2018
comment
Именно поэтому ответ на __proto__ VS. prototype в JavaScript? - person Andreas; 31.03.2018
comment
это хорошо или как насчет Foo.collection.push (this) Foo.count ++ - person Selva Ganapathi; 07.07.2019

(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) 
    })()

Попробуйте этот код, чтобы понять

person Timur    schedule 18.07.2018

Есть только один объект, который используется для прототипной цепочки. Очевидно, что у этого объекта есть имя и значение: __proto__ - его имя, а prototype - его значение. Это все.

Чтобы облегчить понимание, посмотрите на диаграмму вверху этого поста (Диаграмма Дмитрия Сошникова), вы никогда не найдете __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 (которое является его прототипом), это именно то, на что указывает __proto__ x. Следовательно, __proto__ действительно указывает на прототип x. Таким образом, __proto__ ссылается на x (указатель на x), а prototype - это значение x (его прототип).

Надеюсь, теперь стало немного ясно.

person Fouad Boukredine    schedule 17.09.2019

Это очень важный вопрос, актуальный для всех, кто хочет понять прототипное наследование. Насколько я понимаю, прототип назначается по умолчанию, когда объект создается с помощью new из функции, потому что функция имеет объект-прототип по определению:

function protofoo(){
}
var protofoo1 = new protofoo();
console.log(protofoo.prototype.toString()); //[object Object]

Когда мы создаем обычный объект без new, то есть явно из функции, у него нет прототипа, но есть пустой прототип, которому можно назначить прототип.

var foo={
  check: 10
};
console.log(foo.__proto__); // empty
console.log(bar.prototype); //  TypeError
foo.__proto__ = protofoo1; // assigned
console.log(foo.__proto__); //protofoo

Мы можем использовать Object.create для явной привязки объекта.

// we can create `bar` and link it to `foo`
var bar = Object.create( foo );
bar.fooprops= "We checking prototypes";
console.log(bar.__proto__); // "foo"
console.log(bar.fooprops); // "We checking prototypes"
console.log(bar.check); // 10 is delegated to `foo`
person tksilicon    schedule 07.05.2020

__proto__ является базой для создания prototype и функции-конструктора, например: function human(){} имеет prototype, который совместно используется через __proto__ в новом экземпляре функции-конструктора. Более подробную информацию см. здесь

person Jyoti Duhan    schedule 13.07.2018
comment
@ Дерик Дэниел: не уверен, почему вы проголосовали против, но внесенное вами изменение было не тем, что я пытался передать. Дальше отредактировал для большего просвета :). - person Jyoti Duhan; 13.07.2018
comment
Джоти, я не голосовал против вашего ответа, это сделал кто-то другой, я просто отредактировал его :) - person Derick Daniel; 13.07.2018

Как это правильно сказано

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

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

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

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

Рассмотрим следующий пример:

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
person Himansh    schedule 02.08.2019

Я понимаю: __proto__ и prototype обслуживаются для техники цепочки прототипов. разница в том, что функции, названные с подчеркиванием (например, __proto__), вообще не предназначены для разработчиков, вызываемых явно. другими словами, они предназначены только для некоторых механизмов, таких как наследование и т. д., они являются «внутренними». но функции, названные без подчеркивания, предназначены для явного вызова, они являются «интерфейсными».

person 成 周    schedule 25.06.2014
comment
__proto__ и prototype - это нечто большее, чем просто соглашение об именах. Они могут указывать или не указывать на один и тот же объект. См. Ответ @zyklus. - person demisx; 25.08.2014
comment
@demisx, конечно, вы правы, но я считаю, что разница в названиях показывает контраст функциональности. - person 成 周; 11.10.2014
comment
Недостаточно просто заявить в соответствии с вашим пониманием, особенно когда другие хорошие ответы были предоставлены ранее ... - person ProfNandaa; 08.08.2015

!!! ЭТО ЛУЧШЕЕ ОБЪЯСНЕНИЕ В МИРЕ !!!!!

var q = {}
var prototype = {prop: 11}

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

в конструкторах функций механизм JavaScript вызывает это q.__proto__ = prototype автоматически, когда мы пишем new Class, а в __proto__ prop set Class.prototype

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

Наслаждаться %)

person Maxmaxmaximus    schedule 18.07.2016