РЕДАКЦІЯ Лютий 2012: відповідь нижче не є точною. __proto__ додається до ECMAScript 6 як "нормативний факультативний", що означає, що його не потрібно застосовувати, але якщо він є, він повинен дотримуватися заданого набору правил. Наразі це не вирішено, але принаймні це буде офіційно частиною специфікації JavaScript.
Це питання є набагато складнішим, ніж це виглядає на поверхні, і вищий рівень оплати більшості людей щодо знання внутрішніх програм Javascript.
prototype
Властивість об'єкта використовується при створенні нових дочірніх об'єктів цього об'єкта. Зміна його не відображається в самому об'єкті, а відображається тоді, коли цей об'єкт використовується як конструктор для інших об'єктів і не має користі в зміні прототипу існуючого об'єкта.
function myFactory(){};
myFactory.prototype = someOtherObject;
var newChild = new myFactory;
newChild.__proto__ === myFactory.prototype === someOtherObject; //true
Об'єкти мають внутрішнє [[прототип]] властивість, яке вказує на поточний прототип. Як він працює, кожен раз, коли називається властивість на об'єкті, він починається від об'єкта, а потім проходить по ланцюгу [[прототип]], поки не знайде збіг або не вдасться після прототипу кореневого об'єкта. Ось як Javascript дозволяє будувати час виконання та змінювати об'єкти; у нього є план пошуку того, що йому потрібно.
__proto__
Властивість існує в деяких реалізаціях (зараз багато): будь-яка реалізацію Mozilla, все WebKit один я знаю, деякі інші. Це властивість вказує на внутрішнє [[прототип]] властивості та дозволяє змінювати пост-створення на об'єктах. Будь-які властивості та функції миттєво переключаються на відповідність прототипу завдяки цьому ланцюговому пошуку.
Ця функція, хоча зараз є стандартизованою, все ще не є обов'язковою частиною 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 ніколи не буде). Цілком ймовірно, що він буде працювати в веб-казі та мозі протягом наступних 10 років, оскільки ES6 не буде доопрацьовано до 2013 року.
Brendan Eich - re: Підхід до нових методів об'єктів у ES5 :
Вибачте, ... але налаштований __proto__
, окрім випадку використання об'єкта ініціалізатора (тобто, на новому об'єкті, який ще не доступний, аналогічно ES5 в Object.create), є жахливою ідеєю. Я пишу це, розробивши та впровадивши програму __proto__
12 років тому.
... відсутність стратифікації є проблемою (розгляньте дані JSON за допомогою ключа "__proto__"
). І ще гірше, що мутаційність означає, що реалізації повинні перевірити наявність циклічних ланцюгів прототипу, щоб уникнути ілопінгу. [необхідні постійні перевірки на нескінченну рекурсію]
Нарешті, мутація __proto__
існуючого об'єкта може порушити негенеричні методи в новому об'єкті-прототипі, який не може працювати на приймальному (прямому) об'єкті, __proto__
який встановлюється. Це просто погана практика, форма навмисного типу плутанини взагалі.