В предыдущей статье упоминалось свойство __proto__, как я и обещал опишу его в данной статье.

Итак, любой объект в JavaScript имеет свойство __proto__. Это скрытое системное свойство. В некоторых реализациях интерпретатора оно было недоступно и вообще использование его напрямую не рекомендуется. (В прошлой статье это свойство использовалось исключительно с доказательной целью. Требовалось обойти ограничение, в связи с которым не удавалось поменять предка класса в конструкторе последнего.)

При обращении к любому свойству объекта, оно в первую очередь ищется в самом объекте:

var obj = {itsProperty: 1};

console.log(obj.itsProperty);// 1


Но если его там нет, поиск происходит в свойстве __proto__:

obj.__proto__ = {protoProperty: 2};

console.log(obj.protoProperty);// 2


Если его нет и там, оно ищется дальше по цепочке:

obj.__proto__.__proto__ = {protosPotoProperty: 3};

console.log(obj. protosPotoProperty);// 3


Эта цепочка называется цепочкой прототипов (prototype chain).



Ничего не напоминает? То же самое мы видели при работе с prototype. Наверное, вы уже догадались, что эти два понятия как-то связаны. Говоря простым языком, для любого объекта(кроме null и undefined) __proto__ это ссылка на объект, являющийся прототипом его типа данных. В терминах JavaScript данное утверждение можно заменить следующим тождеством:

x.constructor.prototype===x.__proto__


Для любого объекта х (как уже говорилось, кроме null и undefined) приведенный выше код выведет true.



Использование свойства __proto__ в скриптах



Как я уже писал ранее, свойство __proto__ является скрытым, и не описано в спецификации языка. Соответственно, использовать его (как сделал я в предыдущей статье) крайне нежелательно. А уж использовать его напрямую и вообще опасно, поскольку это привязывает скрипт к конкретной реализации интерпретатора. Поскольку эта реализация недокументированна, ее могут поменять в любой момент, и написанный код перестанет работать в следующей же версии браузера.



Если Вам все же необходимо поменять свойство __proto__, то спецификация ECMA Script 5 содержит два метода позволяющие «безопасно» манипулировать этим свойством. Это методы Object.create и Object.getPrototypeOf.

Логика их работы такова:

var obj = Object.create({a: 1});
Создает объект, в свойство __proto__ которого помещается переданный объект.



Object.getPrototypeOf(obj).a = 1;
Переопределяет свойство a для __proto__ уже созданного объекта.





Как я уже упоминал, данные методы появились в спецификации ECMA Script 5, поэтому в браузерах с более ранними версиями JavaScript они не доступны. Для этого случая рекомендую использовать библиотеку github.com/kriskowal/es5-shim.



Вот собственно и все, что я хотел рассказать о свойстве __proto__. Единственное, что хотелось бы повторить, старайтесь не использовать данное свойство без необходимости (в том числе с помощью методов Object.create и Object.getPrototypeOf). В 99.9% случаев его использование не требуется, но ухудшает «читабельность» кода.



Спасибо за внимание.
0

Комментарии

Для того, чтоб оставлять комментарии или зарегистрируйтесь.