РЕДАКТИРОВАТЬ Февраль 2012: ответ ниже не является точным.__proto__ добавляется в ECMAScript 6 как «необязательный нормативный», что означает, что его не нужно реализовывать, но если это так, он должен следовать заданному набору правил.В настоящее время это не решено, но, по крайней мере, оно будет официально частью спецификации JavaScript.
Этот вопрос намного сложнее, чем кажется на первый взгляд, и выходит за рамки уровня оплаты труда большинства людей в отношении знанийвнутренних компонентов Javascript.
Свойство prototype
объекта используется при создании новых дочерних объектов этого объекта.Его изменение не отражается в самом объекте, а отражается, когда этот объект используется в качестве конструктора для других объектов, и не имеет смысла изменять прототип существующего объекта.
function myFactory(){};
myFactory.prototype = someOtherObject;
var newChild = new myFactory;
newChild.__proto__ === myFactory.prototype === someOtherObject; //true
Объекты имеютвнутреннее свойство [[prototype]], которое указывает на текущий прототип.Он работает так, что всякий раз, когда вызывается свойство объекта, оно начинается с объекта, а затем идет вверх по цепочке [[prototype]], пока не найдет совпадение или потерпит неудачу после прототипа корневого объекта.Вот как Javascript позволяет создавать и модифицировать объекты во время выполнения;у него есть план поиска того, что ему нужно.
Свойство __proto__
существует в некоторых реализациях (сейчас много): любая реализация Mozilla, все известные мне webkit, некоторые другие.Это свойство указывает на внутреннее свойство [[prototype]] и позволяет модифицировать пост-создание объектов.Любые свойства и функции будут мгновенно переключаться в соответствии с прототипом благодаря этому цепочечному поиску.
Эта функция, будучи стандартизированной в настоящее время, по-прежнему не является обязательной частью JavaScript, и в языках, поддерживающих ее, высокая вероятностьсбивая ваш код в категорию «неоптимизированные».Механизмы JS должны делать все возможное для классификации кода, особенно «горячего» кода, к которому часто обращаются, и если вы делаете что-то необычное, например, изменение __proto__
, они вообще не будут оптимизировать ваш код.
В этих публикациях https://bugzilla.mozilla.org/show_bug.cgi?id=607863 конкретно обсуждаются текущие реализации __proto__
и различия между ними.Каждая реализация делает это по-своему, потому что это сложная и нерешенная проблема.Все в Javascript является изменчивым, кроме a.) Синтаксиса b.) Хост-объектов (технически DOM существует вне Javascript) и c.) __proto__
.Все остальное полностью в руках вас и любого другого разработчика, так что вы можете понять, почему __proto__
торчит как больной большой палец.
Есть одна вещь, которую __proto__
допускает, что в противном случае сделать невозможно: обозначение прототипа объекта во время выполнения отдельно от его конструктора.Это важный вариант использования и одна из основных причин, по которой __proto__
еще не умер.Достаточно важно, чтобы это было серьезным предметом обсуждения в формулировке Harmony или скоро станет известным как ECMAScript 6. Возможность указать прототип объекта во время создания будет частью следующей версии Javascript, и это будетколокол, обозначающий __proto__
дни, формально пронумерован.
В краткосрочной перспективе вы можете использовать __proto__
, если вы нацеливаетесь на браузеры, которые его поддерживают (не IE, и ни один IE не будет).Вполне вероятно, что он будет работать в webkit и moz в течение следующих 10 лет, так как ES6 не будет завершен до 2013 года.
Brendan Eich - re: Подход новых методов объектав ES5 :
Извините, ... но можно установить __proto__
, за исключением случая использования инициализатора объекта (т. е. для нового объекта, который еще не доступен, аналог ES. Object.create), это ужасная идея.Я пишу это, спроектировав и установив settable __proto__
более 12 лет назад.
... проблема отсутствия стратификации (рассмотрим данные JSON с ключом "__proto__"
).И что еще хуже, изменчивость означает, что реализации должны проверять циклические цепочки прототипов, чтобы избежать ошибок. [требуются постоянные проверки бесконечной рекурсии]
Наконец, изменение __proto__
в существующем объекте может нарушить неуниверсальные методы в новом объекте-прототипе, которые не могут работать с объектом-получателем (прямым), чей __proto__
устанавливается.Это просто плохая практика, форма намеренного смешения типов, в общем.