Цепочки прототипов - Promise в частности

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

(Оговорки)
После очередного прочтения источников, предполагаю что:
Prototype - объект существующий почти в каждой функции (за исключением fetch и подобных);
[[Prototype]] - внутренний слот каждого объекта в JS - ссылка на родительский Prototype, доступ к которой можно получить через легаси __proto__ (является геттером и сеттером этой скрытой ссылки);


Пробую эксперементировать. Вывожу экземпляр объекта в devtools, иду по цепочке прототипов до null разными путями:

const obj = new Object;
// Путь constructor-prototype:
// obj -> [[Prototype]]: -> constructor -> prototype -> __proto__: null
// (Ожидаемый результат)

// Путь __proto__, [[Prototype]]:
// obj -> [[Prototype]] -> __proto__ -> __proto__: null
// (Почти ожидаемый результат)

// Делаю выводы: 
// 1) __proto__ === constructor.prototype (по определениям)
// 2) prototype === prototype.constructor.prototype
// 3) Возможно переход "obj->[[Prototype]]" это не ссылка на родительский прототип, а  
// локальный скрытый объект внутри obj (Потому что если бы возвращался родительский  
// прототип, то путь до null был бы короче: obj->[[Prototype]]->__proto__: null).

Решаю далее походить по цепочкам производных встроенных объектов, например промиса:

const p = Promise.resolve();
// Путь constructor-prototype:
// p -> [[Prototype]] -> constructor -> prototype -> [[Prototype]] -> __proto__ -> __proto__: null
// (Почти ожидаемый результат)

// Путь __proto__, [[Prototype]]:
// p -> [[Prototype]]: Promise -> [[Prototype]]: Object* -> __proto__: Promise -> \
//      [[Prototype]]: -> __proto__ -> __proto__: null
// (What?)

Откуда в цепи взялся доп.объект*? Вначале подумал, возможно это какой-то внутренний процесс, и он появляется из-за создания экземпляра промиса, но ведь p.__proto__.__proto__.__proto__ === null, а значит на деле этого объекта нет...

Является ли instance->[[Prototype]]->* внутренним объектом этого инстанса, или же объектом родителя? Если объектом родителя, то почему для перехода к "деду" нужно сделать странный мув вроде *->constructor->prototype->[[Prototype]] или *->[[Prototype]]->__proto__, а не обычный *->__proto__ (aka *->[[Prototype]])?

Наконец, почему иногда встречается __proto__, а иногда [[Prototype]]? Можно ли условно считать их однозначными в контексте перемещения к null?

Возможно я не вижу чего-то в упор, но последние дни были несколько тяжёлыми. Буду рад услышать ваши мысли

p.s. Изучил довольно много источников (включая англоязычных), но самым лучшим показалась эта статья https://habr.com/ru/articles/518360/ (опирался на неё)


Ответы (0 шт):