Что находится в Object.__proto__?

В javascript Google Chrom объекты имеют свойство с именем __proto__, которое указывает на их прототип (или родительский) объект.

var foo = {};
console.log(foo.__proto__ === Object.prototype);    //returns true

Однако это неверно для объекта Object.

console.log(Object.__proto__ === Object.prototype);    //returns false

Свойство Object.__proto__ выглядит как пустой метод.

> console.log(Object.__proto__.toString());
function () {}

Что такое функция Object.__proto__, помимо того, что она служит предупреждением о том, чтобы полагаться на функции javascript, которые начинаются за пределами стандартных тел?


person Alan Storm    schedule 01.12.2016    source источник
comment
Object.__proto__ === Function.prototype ...Объект - это функция. typeof Object === "function"   -  person    schedule 02.12.2016
comment
Вы читали этот документ? Это может прояснить некоторые вещи. developer.mozilla.org/en-US/ документы/Интернет/JavaScript/Справочник/   -  person Hampus    schedule 02.12.2016
comment
... и __proto__ был добавлен в ECMAScript 6.   -  person    schedule 02.12.2016
comment
... и причина, по которой Function.prototype кажется пустой функцией, заключается в том, что многие прототипы встроенных конструкторов на самом деле являются экземплярами объекта, который они создают. Например, Array.isArray(Array.prototype); // true (Или, может быть, не совсем экземпляр, но они имеют какое-то отношение к конструктору.)   -  person    schedule 02.12.2016
comment
@прищурившись, ...и Function.__proto__===Function.prototype   -  person Octopus    schedule 02.12.2016
comment
Ах, спасибо, @squint. Object.__proto__ === Function.prototype правда и Object.__proto__.__proto__ === Object.prototype правда прояснили это для меня. Я всегда предполагал, что Object и Function находятся на одном уровне иерархии, и что прототипом Object был Object.prototype. Если вы хотите добавить какую-то версию своего комментария в качестве ответа, я буду рад отметить ее как лучшую.   -  person Alan Storm    schedule 02.12.2016
comment
Пожалуйста. Я слишком устал, чтобы составить достойный ответ, поэтому не стесняйтесь собирать воедино то, что я написал, и все, что вы выяснили, и вместо этого опубликовать ответ.   -  person    schedule 02.12.2016
comment
Еще раз спасибо @squint - сделано и ниже.   -  person Alan Storm    schedule 05.12.2016


Ответы (2)


Верхняя часть графа объектов сформирована так, чтобы максимально соответствовать ожиданиям, установленным в других местах спецификации.

Обязательно наступает момент, когда обычные связи объектов не могут использоваться, потому что у вас «исчерпаны объекты».

Базовое понимание JavaScript позволяет нам ожидать, что [[Prototype]] из Object будет свойством-прототипом функции, используемой для создания объекта-функции Object.

Мы ожидаем, что Function будут созданы с использованием объекта-функции Function, поэтому...

Object.__proto__ === Function.prototype

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

Function.__proto__ === Function.prototype

Таким образом обеспечивая Function instanceof Function === true.

Мы можем показать, что Function.prototype является особым объектом-функцией, потому что:

Function.prototype.prototype === undefined

... и каждая пользовательская функция (кроме толстых стрелок) имеет объект в своем свойстве прототипа.

Из-за всего вышеперечисленного:

Object.__proto__ === Function.__proto__

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

Теперь TC-39 нужно было определить, что такое [[Prototype]] из [[Prototype]] из Object. Согласно вышеизложенному мы знаем, что [[Prototype]] из Object равно Function.prototype.

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

Это означает, что вершину каждой цепочки прототипов можно удобно связать с Object.prototype.

Это, конечно, также отвечает желаемому требованию, что все «является объектом».

Object.__proto__.__proto__ === Object.prototype 

На этом этапе нам нужно завершить граф объекта, поэтому мы устанавливаем [[Prototype]] из Object.prototype равным null.

Object.__proto__.__proto__.__proto__ === null
person Ben Aston    schedule 01.12.2016
comment
Полезная информация @BenAston -- спасибо! но я не уверен, что информация Object.__proto__ верна? Object.__proto__.toString() возвращает "function () {}" -- то есть пустую функцию, не функцию [native code] (Chrome, OS X El Cap)? Re: за пределами стандартных тел мое заявление/шутка было неясным. Насколько я понимаю, proto был реализован в браузерах, несмотря на то, что он не является частью стандарта ES, и лишь недавно был включен в стандарт ES6. - person Alan Storm; 02.12.2016
comment
Отображение Object.__proto__.toString() будет зависеть от версии вашего браузера. Также: вы хотите, чтобы toString распечатал исходный код C++? Если вы мне не верите: скажите, какая пользовательская функция создала встроенный Object объект-функцию? - person Ben Aston; 02.12.2016
comment
Причина, по которой я не уверен, что ваше описание на 100% точное, заключается в том, что если я регистрирую функцию с собственным кодом в браузере Chrome (или использую метод toString), я получаю что-то, что упоминает [собственный код] (function split() { [native code] }. Однако, когда Chrome (или .toString) отображает объект Object.__proto__, он не включает собственный код и выглядит как пустая функция пользователя (function() {}) - person Alan Storm; 02.12.2016
comment
Downvoter, пожалуйста, объясните! Если я ошибаюсь, пожалуйста, объясните, как я могу извлечь уроки из своей ошибки. - person Ben Aston; 02.12.2016
comment
Проголосовали за неправильную информацию о функциях Native Code. Голосование против удалено теперь, когда этого больше нет. - person Alan Storm; 05.12.2016

Основываясь на комментариях squint выше, я смог разобраться в этом. Мое неустановленное, неверное (и более 10 лет) предположение заключалось в том, что объект-прототип глобального вспомогательного объекта Object также был «прототипом прототипов» верхнего уровня в верхней/конце цепочки прототипов javascript. Это неправда.

Вспомогательный объект Object и вспомогательный объект Function имеют один и тот же родительский объект-прототип.

console.log( Object.__proto__ === Function.__proto__ );    //true

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

console.log( Object.__proto__.__proto__ === Object.prototype );         //true

Я также составил краткую диаграмму, отображающую реальные прототипы нескольких низкоуровневых вспомогательных/конструкторских объектов Javascript.

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

Наконец, я также обнаружил, что в Google Chrome реализован объект Reflect, который включает в себя метод getPrototypeOf, который выглядит так же, как и метод Object.getPrototypeOf.

person Alan Storm    schedule 02.12.2016
comment
Re: проголосовавшие против - если что-то выше неверно, пожалуйста, дайте мне знать. Если это правильно, но вам не нравится моя точка зрения - думаю, я буду жить с минусами;) - person Alan Storm; 05.12.2016
comment
Я думаю, вы правы, но график сбивает с толку, потому что я ожидаю, что стрелки будут указывать в другом направлении (в направлении наследования). И это предложение сбивает с толку: Вспомогательный объект Object имеет тот же прототип, что и вспомогательный объект Function. Формулировка расплывчата. Я не могу сказать, когда вы говорите о функциях-конструкторах, их .prototype или объекте, от которого они наследуются (который доступен через __proto__). Так что это может быть частью причины для DV. - person ; 05.12.2016
comment
getPrototypeOf является новым для объекта Reflect, но он существует уже довольно давно через Object.getPrototypeOf. По крайней мере, я думаю, что они одинаковы. На Reflect пока особо не смотрел. РЕДАКТИРОВАТЬ: я вижу в документах, что они действительно одинаковы. Хороший. - person ; 05.12.2016
comment
Изменена формулировка, чтобы сделать ее более четкой, и обновлена ​​диаграмма, чтобы стрелки указывали назад к вершине иерархии. Кроме того, FWIW, в большинстве документов отсутствует ясность в отношении свойства .prototype и истинного прототипа родительского объекта объекта, что в первую очередь привело к этому вопросу. Еще раз спасибо за помощь @squint! - person Alan Storm; 05.12.2016