Бесконечное прототипного наследования в JavaScript
Я изучаю прототипное наследование в Javascript, и для моего понимания я пытаюсь использовать его, чтобы отправить процесс в бесконечную рекурсивную цепочку.
Моя идея прототипического наследования состоит в том, что объект (который является функцией) содержит прототипную связь. Любой экземпляр этого объекта указывает на него. Так что если я скажу пример.someproperty он смотрит в цепочку прототипов родительского объекта.Предполагая это, если я просто укажу список прототипов функции на себя, он должен войти в бесконечный цикл, когда объект пытается получить доступ к некоторому свойству.
var p = function(){};
p.prototype = p;
// I also tried p.prototype = new p();
var q = new p();
// and now when I say q.something, it should never be able to find it.
Я хочу знать, почему это не работает и как я могу заставить его войти в бесконечный цикл.2 ответа:
Используя более общий стиль:
function P(){}; P.prototype = P;В ECMA-262 свойствовнутреннего прототипа обозначается через
[[Prototype]].Присвоение другого объекта P. prototype не изменяет P ' s
[[Prototype]], поэтому его цепочка наследования остается такой:P : P[[Prototype]] -> Function.prototype -> Object.prototype -> nullУчитывая, что P и P. прототип указывают на один и тот же объект, цепочка
[[prototype]]экземпляра P имеет вид:p : p[[Prototype]] -> P : P[[Prototype]] -> Function.prototype -> Object.prototype -> nullТак что никакой бесконечной петли.
Без назначение P. прототип, цепочка прототипов p была бы следующей:
p : p[[Prototype]] -> P.prototype -> Object.prototype -> nullЧтобы получить бесконечный цикл, вы можете назначить объекту его собственное свойство
__proto__(открытый способ доступа к[[Prototype]]) в тех браузерах, которые его поддерживают, но я не уверен, что это хорошая идея, Firefox бросает:"TypeError: cyclic __proto__ value".
Что ж, к вашему первому вопросу:
var p = function(){}; p.prototype = p; // I also tried p.prototype = new p(); var q = new p();В первом случае все, что вы делаете при создании экземпляра
Второй немного отличается-близко, но без сигары. Когда вы присваиваетеp, - это устанавливаете прототип для самой функцииp, которая является объектом в своем собственном праве (с такими свойствами, какlength,prototype, и т.д.). Его фактическим внутренним прототипом являетсяFunction.prototype, который, в свою очередь, имеет прототипObject.prototype.new p()p.prototype, свойствоprototypeне установлено тем не менее, таким образом, вы просто получите исходное значение свойстваprototypeв качестве внутреннего прототипа экземпляра.
Перейдем к вашему второму вопросу. Я на самом деле не понимаю, почему вы это делаете, поскольку каждое свойство будет затенено собственным свойством экземпляра.
Даже если бы вам разрешили (браузеры этого не делают), в этом не было бы никакого смысла.
Рассмотрим это:
var a = { b: 1 }; a.__proto__ = a;Предположим, что это работает, игнорируя тот факт, что это выбрасывает TypeError во всех браузерах (который указан для браузеров в приложении B предстоящей спецификации ES6).
Если бы вы получили доступ к свойствуb, Вы бы никогда не поднялись по цепочке прототипов.Если вы попытаетесь получить доступ к несуществующему свойству, реализация (если она допускает такое) может либо подняться вверх по цепочке прототипов, вернуться к себе рекурсивно, либо признать, что свойство никогда не будет найдено и возвратиться неопределенным.
Конечно, есть ситуация, когда есть несколько вовлеченные объекты:
Однако это до смешного глупо и не имеет практической пользы (если это вообще разрешено-это не так).var a = { x: 1 }; var b = { y: 2 }; b.__proto__ = a; a.__proto__ = b;