ÐбÑекÑÑ Ð² JavaScript можно оÑганизоваÑÑ Ð² ÑепоÑки Ñак, ÑÑÐ¾Ð±Ñ ÑвойÑÑво, не найденное в одном обÑекÑе, авÑомаÑиÑеÑки иÑкалоÑÑ Ð±Ñ Ð² дÑÑгом.
СвÑзÑÑÑим звеном вÑÑÑÑÐ¿Ð°ÐµÑ ÑпеÑиалÑное ÑвойÑÑво __proto__.
ÐÑоÑоÑип proto
ÐÑли один обÑÐµÐºÑ Ð¸Ð¼ÐµÐµÑ ÑпеÑиалÑнÑÑ ÑÑÑÐ»ÐºÑ __proto__ на дÑÑгой обÑекÑ, Ñо пÑи ÑÑении ÑвойÑÑва из него, еÑли ÑвойÑÑво оÑÑÑÑÑÑвÑÐµÑ Ð² Ñамом обÑекÑе, оно иÑеÑÑÑ Ð² обÑекÑе __proto__.
СвойÑÑво __proto__ доÑÑÑпно во вÑеÑ
бÑаÑзеÑаÑ
, кÑоме IE10-, а в более ÑÑаÑÑÑ
IE оно, конеÑно же, Ñоже еÑÑÑ, но напÑÑмÑÑ Ðº Ð½ÐµÐ¼Ñ Ð½Ðµ обÑаÑиÑÑÑÑ, ÑÑебÑÑÑÑÑ ÑÑÑÑ Ð±Ð¾Ð»ÐµÐµ ÑложнÑе ÑпоÑобÑ, коÑоÑÑе Ð¼Ñ ÑаÑÑмоÑÑим позднее.
ÐÑÐ¸Ð¼ÐµÑ ÐºÐ¾Ð´Ð° (кÑоме IE10-):
var animal = {
eats: true
};
var rabbit = {
jumps: true
};
rabbit.__proto__ = animal;
// в rabbit можно найÑи оба ÑвойÑÑва
alert( rabbit.jumps ); // true
alert( rabbit.eats ); // true
- ÐеÑвÑй
alertздеÑÑ ÑабоÑÐ°ÐµÑ Ð¾ÑевиднÑм обÑазом â он вÑÐ²Ð¾Ð´Ð¸Ñ ÑвойÑÑвоjumpsобÑекÑаrabbit. - ÐÑоÑой
alertÑ Ð¾ÑÐµÑ Ð²ÑвеÑÑиrabbit.eats, иÑÐµÑ ÐµÐ³Ð¾ в Ñамом обÑекÑеrabbit, не Ð½Ð°Ñ Ð¾Ð´Ð¸Ñ â и пÑÐ¾Ð´Ð¾Ð»Ð¶Ð°ÐµÑ Ð¿Ð¾Ð¸Ñк в обÑекÑеrabbit.__proto__, Ñо еÑÑÑ, в данном ÑлÑÑае, вanimal.
ÐллÑÑÑÑаÑÐ¸Ñ Ð¿ÑоиÑÑ
одÑÑего пÑи ÑÑении rabbit.eats (поиÑк идÑÑ ÑÐ½Ð¸Ð·Ñ Ð²Ð²ÐµÑÑ
):
ÐбÑекÑ, на коÑоÑÑй ÑказÑÐ²Ð°ÐµÑ ÑÑÑлка __proto__, назÑваеÑÑÑ Â«Ð¿ÑоÑоÑипом». Рданном ÑлÑÑае полÑÑилоÑÑ, ÑÑо animal ÑвлÑеÑÑÑ Ð¿ÑоÑоÑипом Ð´Ð»Ñ rabbit.
Также говоÑÑÑ, ÑÑо обÑÐµÐºÑ rabbit «пÑоÑоÑипно наÑледÑеÑ» Ð¾Ñ animal.
ÐбÑаÑим внимание â пÑоÑоÑип иÑполÑзÑеÑÑÑ Ð¸ÑклÑÑиÑелÑно пÑи ÑÑении. ÐапиÑÑ Ð·Ð½Ð°ÑениÑ, напÑимеÑ, rabbit.eats = value или Ñдаление delete rabbit.eats â ÑабоÑÐ°ÐµÑ Ð½Ð°Ð¿ÑÑмÑÑ Ñ Ð¾Ð±ÑекÑом.
РпÑимеÑе ниже Ð¼Ñ Ð·Ð°Ð¿Ð¸ÑÑваем ÑвойÑÑво в Ñам rabbit, поÑле Ñего alert пеÑеÑÑаÑÑ Ð±ÑаÑÑ ÐµÐ³Ð¾ Ñ Ð¿ÑоÑоÑипа, а беÑÑÑ Ñже из Ñамого обÑекÑа:
var animal = {
eats: true
};
var rabbit = {
jumps: true,
eats: false
};
rabbit.__proto__ = animal;
alert( rabbit.eats ); // false, ÑвойÑÑво взÑÑо из rabbit
ÐÑÑгими Ñловами, пÑоÑоÑип â ÑÑо «ÑезеÑвное Ñ ÑанилиÑе ÑвойÑÑв и меÑодов» обÑекÑа, авÑомаÑиÑеÑки иÑполÑзÑемое пÑи поиÑке.
У обÑекÑа, коÑоÑÑй ÑвлÑеÑÑÑ __proto__, Ð¼Ð¾Ð¶ÐµÑ Ð±ÑÑÑ Ñвой __proto__, Ñ Ñого â Ñвой, и Ñак далее. ÐÑи ÑÑом ÑвойÑÑва бÑдÑÑ Ð¸ÑкаÑÑÑÑ Ð¿Ð¾ ÑепоÑке.
ÐÑли Ð²Ñ Ð±ÑдеÑе ÑиÑаÑÑ ÑпеÑиÑикаÑÐ¸Ñ ECMAScript â ÑвойÑÑво __proto__ обознаÑено в ней как [[Prototype]].
ÐвойнÑе квадÑаÑнÑе Ñкобки здеÑÑ Ð²Ð°Ð¶Ð½Ñ, ÑÑÐ¾Ð±Ñ Ð½Ðµ пеÑепÑÑаÑÑ ÐµÐ³Ð¾ Ñ ÑовÑем дÑÑгим ÑвойÑÑвом, коÑоÑое назÑваеÑÑÑ prototype, и коÑоÑое Ð¼Ñ ÑаÑÑмоÑÑим позже.
ÐеÑод hasOwnProperty
ÐбÑÑнÑй Ñикл for..in не Ð´ÐµÐ»Ð°ÐµÑ ÑазлиÑÐ¸Ñ Ð¼ÐµÐ¶Ð´Ñ ÑвойÑÑвами обÑекÑа и его пÑоÑоÑипа.
Ðн пеÑебиÑÐ°ÐµÑ Ð²ÑÑ, напÑимеÑ:
var animal = {
eats: true
};
var rabbit = {
jumps: true,
__proto__: animal
};
for (var key in rabbit) {
alert( key + " = " + rabbit[key] ); // вÑÐ²Ð¾Ð´Ð¸Ñ Ð¸ "eats" и "jumps"
}
Ðногда Ñ Ð¾ÑеÑÑÑ Ð¿Ð¾ÑмоÑÑеÑÑ, ÑÑо Ð½Ð°Ñ Ð¾Ð´Ð¸ÑÑÑ Ð¸Ð¼ÐµÐ½Ð½Ð¾ в Ñамом обÑекÑе, а не в пÑоÑоÑипе.
ÐÑзов obj.hasOwnProperty(prop) возвÑаÑÐ°ÐµÑ true, еÑли ÑвойÑÑво prop пÑÐ¸Ð½Ð°Ð´Ð»ÐµÐ¶Ð¸Ñ ÑÐ°Ð¼Ð¾Ð¼Ñ Ð¾Ð±ÑекÑÑ obj, инаÑе false.
ÐапÑимеÑ:
var animal = {
eats: true
};
var rabbit = {
jumps: true,
__proto__: animal
};
alert( rabbit.hasOwnProperty('jumps') ); // true: jumps пÑÐ¸Ð½Ð°Ð´Ð»ÐµÐ¶Ð¸Ñ rabbit
alert( rabbit.hasOwnProperty('eats') ); // false: eats не пÑинадлежиÑ
ÐÐ»Ñ Ñого, ÑÑÐ¾Ð±Ñ Ð¿ÐµÑебÑаÑÑ ÑвойÑÑва Ñамого обÑекÑа, доÑÑаÑоÑно пÑоÑилÑÑÑоваÑÑ key ÑеÑез hasOwnProperty:
var animal = {
eats: true
};
var rabbit = {
jumps: true,
__proto__: animal
};
for (var key in rabbit) {
if (!rabbit.hasOwnProperty(key)) continue; // пÑопÑÑÑиÑÑ "не Ñвои" ÑвойÑÑва
alert( key + " = " + rabbit[key] ); // вÑÐ²Ð¾Ð´Ð¸Ñ ÑолÑко "jumps"
}
Object.create(null)
ÐаÑаÑÑÑÑ Ð¾Ð±ÑекÑÑ Ð¸ÑполÑзÑÑÑ Ð´Ð»Ñ Ñ ÑÐ°Ð½ÐµÐ½Ð¸Ñ Ð¿ÑоизволÑнÑÑ Ð·Ð½Ð°Ñений по клÑÑÑ, как коллекÑиÑ:
var data = {};
data.text = "ÐÑивеÑ";
data.age = 35;
// ...
ÐÑи далÑнейÑем поиÑке в ÑÑой коллекÑии Ð¼Ñ Ð½Ð°Ð¹Ð´Ñм не ÑолÑко text и age, но и вÑÑÑоеннÑе ÑÑнкÑии:
var data = {};
alert(data.toString); // ÑÑнкÑиÑ, Ñ
оÑÑ Ð¼Ñ ÐµÑ ÑÑда не запиÑÑвали
ÐÑо Ð¼Ð¾Ð¶ÐµÑ Ð±ÑÑÑ Ð½ÐµÐ¿ÑиÑÑнÑм ÑÑÑпÑизом и пÑиводиÑÑ Ðº оÑибкам, еÑли Ð½Ð°Ð·Ð²Ð°Ð½Ð¸Ñ ÑвойÑÑв пÑÐ¸Ñ Ð¾Ð´ÑÑ Ð¾Ñ Ð¿Ð¾ÑеÑиÑÐµÐ»Ñ Ð¸ могÑÑ Ð±ÑÑÑ Ð¿ÑоизволÑнÑми.
ЧÑÐ¾Ð±Ñ ÑÑого избежаÑÑ, Ð¼Ñ Ð¼Ð¾Ð¶ÐµÐ¼ иÑклÑÑаÑÑ ÑвойÑÑва, не пÑинадлежаÑие ÑÐ°Ð¼Ð¾Ð¼Ñ Ð¾Ð±ÑекÑÑ:
var data = {};
// вÑÐ²ÐµÐ´ÐµÑ toString ÑолÑко еÑли оно запиÑано в Ñам обÑекÑ
alert(data.hasOwnProperty('toString') ? data.toString : undefined);
Ðднако, еÑÑÑ Ð¿ÑÑÑ Ð¸ пÑоÑе:
var data = Object.create(null);
data.text = "ÐÑивеÑ";
alert(data.text); // ÐÑивеÑ
alert(data.toString); // undefined
ÐбÑекÑ, ÑоздаваемÑй пÑи помоÑи Object.create(null) не Ð¸Ð¼ÐµÐµÑ Ð¿ÑоÑоÑипа, а знаÑÐ¸Ñ Ð² нÑм Ð½ÐµÑ Ð»Ð¸ÑниÑ
ÑвойÑÑв. ÐÐ»Ñ ÐºÐ¾Ð»Ð»ÐµÐºÑии â как Ñаз Ñо, ÑÑо надо.
ÐеÑÐ¾Ð´Ñ Ð´Ð»Ñ ÑабоÑÑ Ñ proto
Ð ÑовÑеменнÑÑ
бÑаÑзеÑаÑ
еÑÑÑ Ð´Ð²Ð° дополниÑелÑнÑÑ
меÑода Ð´Ð»Ñ ÑабоÑÑ Ñ __proto__. ÐаÑем они нÑжнÑ, еÑли еÑÑÑ __proto__? РобÑем-Ñо, не оÑÐµÐ½Ñ Ð½ÑжнÑ, но по иÑÑоÑиÑеÑким пÑиÑинам Ñоже ÑÑÑеÑÑвÑÑÑ.
- ЧÑение: Object.getPrototypeOf(obj)
- ÐозвÑаÑаеÑ
obj.__proto__(кÑоме IE8-) - ÐапиÑÑ: Object.setPrototypeOf(obj, proto)
- УÑÑанавливаеÑ
obj.__proto__ = proto(кÑоме IE10-).
ÐÑоме Ñого, еÑÑÑ ÐµÑÑ Ð¾Ð´Ð¸Ð½ вÑпомогаÑелÑнÑй меÑод:
- Создание обÑекÑа Ñ Ð¿ÑоÑоÑипом: Object.create(proto, descriptors)
- СоздаÑÑ Ð¿ÑÑÑой обÑÐµÐºÑ Ñ
__proto__, ÑавнÑм пеÑÐ²Ð¾Ð¼Ñ Ð°ÑгÑменÑÑ (кÑоме IE8-), вÑоÑой необÑзаÑелÑнÑй аÑгÑÐ¼ÐµÐ½Ñ Ð¼Ð¾Ð¶ÐµÑ ÑодеÑжаÑÑ Ð´ÐµÑкÑипÑоÑÑ ÑвойÑÑв.
ÐÑого
- Ð JavaScript еÑÑÑ Ð²ÑÑÑоенное «наÑледование» Ð¼ÐµÐ¶Ð´Ñ Ð¾Ð±ÑекÑами пÑи помоÑи ÑпеÑиалÑного ÑвойÑÑва
__proto__. - ÐÑи ÑÑÑановке ÑвойÑÑва
rabbit.__proto__ = animalговоÑÑÑ, ÑÑо обÑекÑanimalбÑÐ´ÐµÑ Â«Ð¿ÑоÑоÑипом»rabbit. - ÐÑи ÑÑении ÑвойÑÑва из обÑекÑа, еÑли его в нÑм неÑ, оно иÑеÑÑÑ Ð²
__proto__. ÐÑоÑоÑип задейÑÑвÑеÑÑÑ ÑолÑко пÑи ÑÑении ÑвойÑÑва. ÐпеÑаÑии пÑиÑвоениÑobj.prop =или ÑдалениÑdelete obj.propÑовеÑÑаÑÑÑÑ Ð²Ñегда над Ñамим обÑекÑомobj.
ÐеÑколÑко пÑоÑоÑипов Ð¾Ð´Ð½Ð¾Ð¼Ñ Ð¾Ð±ÑекÑÑ Ð¿ÑиÑвоиÑÑ Ð½ÐµÐ»ÑзÑ, но можно оÑганизоваÑÑ Ð¾Ð±ÑекÑÑ Ð² ÑепоÑкÑ, когда один обÑÐµÐºÑ ÑÑÑлаеÑÑÑ Ð½Ð° дÑÑгой пÑи помоÑи __proto__, ÑÐ¾Ñ ÑÑÑлаеÑÑÑ Ð½Ð° ÑÑеÑий, и Ñак далее.
Ð ÑовÑеменнÑÑ Ð±ÑаÑзеÑÐ°Ñ ÐµÑÑÑ Ð¼ÐµÑÐ¾Ð´Ñ Ð´Ð»Ñ ÑабоÑÑ Ñ Ð¿ÑоÑоÑипом:
- Object.getPrototypeOf(obj) (кÑоме IE8-)
- Object.setPrototypeOf(obj, proto) (кÑоме IE10-)
- Object.create(proto, descriptors) (кÑоме IE8-)
Ðозможно, Ð²Ð°Ñ ÑмÑÑÐ°ÐµÑ Ð½ÐµÐ´Ð¾ÑÑаÑоÑÐ½Ð°Ñ Ð¿Ð¾Ð´Ð´ÐµÑжка __proto__ в ÑÑаÑÑÑ
IE. Ðо ÑÑо не ÑÑÑаÑно. РпоÑледÑÑÑиÑ
главаÑ
Ð¼Ñ ÑаÑÑмоÑÑим дополниÑелÑнÑе меÑÐ¾Ð´Ñ ÑабоÑÑ Ñ __proto__, вклÑÑÐ°Ñ Ñе, коÑоÑÑе ÑабоÑаÑÑ Ð²ÐµÐ·Ð´Ðµ.
Также Ð¼Ñ ÑаÑÑмоÑÑим, как ÑвойÑÑво __proto__ иÑполÑзÑеÑÑÑ Ð²Ð½ÑÑÑи Ñамого ÑзÑка JavaScript и как оÑганизоваÑÑ ÐºÐ»Ð°ÑÑÑ Ñ ÐµÐ³Ð¾ помоÑÑÑ.
ÐомменÑаÑии
<code>, Ð´Ð»Ñ Ð½ÐµÑколÑÐºÐ¸Ñ ÑÑÑок кода — Ñег<pre>, еÑли болÑÑе 10 ÑÑÑок — ÑÑÑÐ»ÐºÑ Ð½Ð° пеÑоÑниÑÑ (plnkr, JSBin, codepenâ¦)