СвойÑÑво "prototype" ÑиÑоко иÑполÑзÑеÑÑÑ Ð²Ð½ÑÑÑи Ñамого ÑзÑка JavaScript. ÐÑе вÑÑÑоеннÑе ÑÑнкÑии-конÑÑÑÑкÑоÑÑ Ð¸ÑполÑзÑÑÑ ÐµÐ³Ð¾.
СнаÑала Ð¼Ñ ÑаÑÑмоÑÑим деÑали, а заÑем иÑполÑзÑем "prototype" Ð´Ð»Ñ Ð´Ð¾Ð±Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð²ÑÑÑоеннÑм обÑекÑам новой ÑÑнкÑионалÑноÑÑи.
Object.prototype
ÐавайÑе вÑведем пÑÑÑой обÑекÑ:
let obj = {};
alert( obj ); // "[object Object]" ?
Ðде код, коÑоÑÑй генеÑиÑÑÐµÑ ÑÑÑÐ¾ÐºÑ "[object Object]"? ÐÑо вÑÑÑоеннÑй меÑод toString, но где он? obj Ð²ÐµÐ´Ñ Ð¿ÑÑÑ!
â¦Ðо кÑаÑÐºÐ°Ñ Ð½Ð¾ÑаÑÐ¸Ñ obj = {} â ÑÑо Ñо же Ñамое, ÑÑо и obj = new Object(), где Object â вÑÑÑÐ¾ÐµÐ½Ð½Ð°Ñ ÑÑнкÑиÑ-конÑÑÑÑкÑÐ¾Ñ Ð´Ð»Ñ Ð¾Ð±ÑекÑов Ñ ÑобÑÑвеннÑм ÑвойÑÑвом prototype, коÑоÑое ÑÑÑлаеÑÑÑ Ð½Ð° огÑомнÑй обÑÐµÐºÑ Ñ Ð¼ÐµÑодом toString и дÑÑгими.
ÐÐ¾Ñ ÑÑо пÑоиÑÑ Ð¾Ð´Ð¸Ñ:
Ðогда вÑзÑваеÑÑÑ new Object() (или ÑоздаÑÑÑÑ Ð¾Ð±ÑÐµÐºÑ Ñ Ð¿Ð¾Ð¼Ð¾ÑÑÑ Ð»Ð¸ÑеÑала {...}), ÑвойÑÑво [[Prototype]] ÑÑого обÑекÑа ÑÑÑанавливаеÑÑÑ Ð½Ð° Object.prototype по пÑавилам, коÑоÑÑе Ð¼Ñ Ð¾Ð±ÑÑждали в пÑедÑдÑÑей главе:
Таким обÑазом, когда вÑзÑваеÑÑÑ obj.toString(), меÑод беÑÑÑÑÑ Ð¸Ð· Object.prototype.
ÐÑ Ð¼Ð¾Ð¶ÐµÐ¼ пÑовеÑиÑÑ ÑÑо Ñак:
let obj = {};
alert(obj.__proto__ === Object.prototype); // true
// obj.toString === obj.__proto__.toString === Object.prototype.toString
ÐбÑаÑиÑе внимание, ÑÑо по ÑепоÑке пÑоÑоÑипов вÑÑе Object.prototype болÑÑе Ð½ÐµÑ ÑвойÑÑва [[Prototype]]:
alert(Object.prototype.__proto__); // null
ÐÑÑгие вÑÑÑоеннÑе пÑоÑоÑипÑ
ÐÑÑгие вÑÑÑоеннÑе обÑекÑÑ, Ñакие как Array, Date, Function и дÑÑгие, Ñакже Ñ
ÑанÑÑ Ñвои меÑÐ¾Ð´Ñ Ð² пÑоÑоÑипаÑ
.
ÐапÑимеÑ, пÑи Ñоздании маÑÑива [1, 2, 3] внÑÑÑенне иÑполÑзÑеÑÑÑ ÐºÐ¾Ð½ÑÑÑÑкÑÐ¾Ñ Ð¼Ð°ÑÑива Array. ÐоÑÑÐ¾Ð¼Ñ Ð¿ÑоÑоÑипом маÑÑива ÑÑановиÑÑÑ Array.prototype, пÑедоÑÑавлÑÑ ÐµÐ¼Ñ Ñвои меÑодÑ. ÐÑо позволÑÐµÑ ÑÑÑекÑивно иÑполÑзоваÑÑ Ð¿Ð°Ð¼ÑÑÑ.
СоглаÑно ÑпеÑиÑикаÑии, навеÑÑ
Ñ Ð¸ÐµÑаÑÑ
ии вÑÑÑоеннÑÑ
пÑоÑоÑипов наÑ
одиÑÑÑ Object.prototype. ÐоÑÑÐ¾Ð¼Ñ Ð¸Ð½Ð¾Ð³Ð´Ð° говоÑÑÑ, ÑÑо «вÑÑ Ð½Ð°ÑледÑÐµÑ Ð¾Ñ Ð¾Ð±ÑекÑов».
ÐÐ¾Ñ Ð±Ð¾Ð»ÐµÐµ Ð¿Ð¾Ð»Ð½Ð°Ñ ÐºÐ°ÑÑина (Ð´Ð»Ñ ÑÑÑÑ Ð²ÑÑÑоеннÑÑ Ð¾Ð±ÑекÑов):
ÐавайÑе пÑовеÑим пÑоÑоÑипÑ:
let arr = [1, 2, 3];
// наÑледÑÐµÑ Ð»Ð¸ Ð¾Ñ Array.prototype?
alert( arr.__proto__ === Array.prototype ); // true
// заÑем наÑледÑÐµÑ Ð»Ð¸ Ð¾Ñ Object.prototype?
alert( arr.__proto__.__proto__ === Object.prototype ); // true
// и null на веÑÑине иеÑаÑÑ
ии
alert( arr.__proto__.__proto__.__proto__ ); // null
ÐекоÑоÑÑе меÑÐ¾Ð´Ñ Ð² пÑоÑоÑипаÑ
могÑÑ Ð¿ÐµÑеÑекаÑÑÑÑ, напÑимеÑ, Ñ Array.prototype еÑÑÑ Ñвой меÑод toString, коÑоÑÑй вÑÐ²Ð¾Ð´Ð¸Ñ ÑлеменÑÑ Ð¼Ð°ÑÑива ÑеÑез запÑÑÑÑ:
let arr = [1, 2, 3]
alert(arr); // 1,2,3 <-- ÑезÑлÑÑÐ°Ñ Array.prototype.toString
Ðак Ð¼Ñ Ð²Ð¸Ð´ÐµÐ»Ð¸ Ñанее, Ñ Object.prototype еÑÑÑ Ñвой меÑод toString, но Ñак как Array.prototype ближе в ÑепоÑке пÑоÑоÑипов, Ñо беÑÑÑÑÑ Ð¸Ð¼ÐµÐ½Ð½Ð¾ ваÑÐ¸Ð°Ð½Ñ Ð´Ð»Ñ Ð¼Ð°ÑÑивов:
РбÑаÑзеÑнÑÑ
инÑÑÑÑменÑаÑ
, ÑакиÑ
как конÑÐ¾Ð»Ñ ÑазÑабоÑÑика, можно поÑмоÑÑеÑÑ ÑепоÑÐºÑ Ð½Ð°ÑÐ»ÐµÐ´Ð¾Ð²Ð°Ð½Ð¸Ñ (возможно, поÑÑебÑеÑÑÑ Ð¸ÑполÑзоваÑÑ console.dir Ð´Ð»Ñ Ð²ÑÑÑоеннÑÑ
обÑекÑов):
ÐÑÑгие вÑÑÑоеннÑе обÑекÑÑ ÑÑÑÑÐ¾ÐµÐ½Ñ Ð°Ð½Ð°Ð»Ð¾Ð³Ð¸Ñно. Ðаже ÑÑнкÑии â они обÑекÑÑ Ð²ÑÑÑоенного конÑÑÑÑкÑоÑа Function, и вÑе иÑ
меÑÐ¾Ð´Ñ (call/apply и дÑÑгие) беÑÑÑÑÑ Ð¸Ð· Function.prototype. Также Ñ ÑÑнкÑий еÑÑÑ Ñвой меÑод toString.
function f() {}
alert(f.__proto__ == Function.prototype); // true
alert(f.__proto__.__proto__ == Object.prototype); // true, наÑледÑÐµÑ Ð¾Ñ Object
ÐÑимиÑивÑ
Самое Ñложное пÑоиÑÑ Ð¾Ð´Ð¸Ñ Ñо ÑÑÑоками, ÑиÑлами и бÑлевÑми знаÑениÑми.
Ðак Ð¼Ñ Ð¿Ð¾Ð¼Ð½Ð¸Ð¼, они не обÑекÑÑ. Ðо еÑли Ð¼Ñ Ð¿Ð¾Ð¿ÑÑаемÑÑ Ð¿Ð¾Ð»ÑÑиÑÑ Ð´Ð¾ÑÑÑп к иÑ
ÑвойÑÑвам, Ñо Ñогда бÑÐ´ÐµÑ Ñоздан вÑеменнÑй обÑекÑ-обÑÑÑка Ñ Ð¸ÑполÑзованием вÑÑÑоеннÑÑ
конÑÑÑÑкÑоÑов String, Number и Boolean, коÑоÑÑй пÑедоÑÑÐ°Ð²Ð¸Ñ Ð¼ÐµÑÐ¾Ð´Ñ Ð¸ поÑле ÑÑого иÑÑезнеÑ.
ÐÑи обÑекÑÑ ÑоздаÑÑÑÑ Ð½ÐµÐ²Ð¸Ð´Ð¸Ð¼Ð¾ Ð´Ð»Ñ Ð½Ð°Ñ, и болÑÑÐ°Ñ ÑаÑÑÑ Ð´Ð²Ð¸Ð¶ÐºÐ¾Ð² опÑимизиÑÑÐµÑ ÑÑÐ¾Ñ Ð¿ÑоÑеÑÑ, но ÑпеÑиÑикаÑÐ¸Ñ Ð¾Ð¿Ð¸ÑÑÐ²Ð°ÐµÑ ÑÑо именно Ñаким обÑазом. ÐеÑÐ¾Ð´Ñ ÑÑиÑ
обÑекÑов Ñакже наÑ
одÑÑÑÑ Ð² пÑоÑоÑипаÑ
, доÑÑÑпнÑÑ
как String.prototype, Number.prototype и Boolean.prototype.
null и undefined не имеÑÑ Ð¾Ð±ÑекÑов-обÑÑÑокСпеÑиалÑнÑе знаÑÐµÐ½Ð¸Ñ null и undefined ÑÑоÑÑ Ð¾ÑобнÑком. У ниÑ
Ð½ÐµÑ Ð¾Ð±ÑекÑов-обÑÑÑок, Ñак ÑÑо меÑÐ¾Ð´Ñ Ð¸ ÑвойÑÑва им недоÑÑÑпнÑ. Также Ñ Ð½Ð¸Ñ
Ð½ÐµÑ ÑооÑвеÑÑÑвÑÑÑиÑ
пÑоÑоÑипов.
Ðзменение вÑÑÑоеннÑÑ Ð¿ÑоÑоÑипов
ÐÑÑÑоеннÑе пÑоÑоÑÐ¸Ð¿Ñ Ð¼Ð¾Ð¶Ð½Ð¾ изменÑÑÑ. ÐапÑимеÑ, еÑли добавиÑÑ Ð¼ÐµÑод к String.prototype, меÑод ÑÑановиÑÑÑ Ð´Ð¾ÑÑÑпен Ð´Ð»Ñ Ð²ÑеÑ
ÑÑÑок:
String.prototype.show = function() {
alert(this);
};
"BOOM!".show(); // BOOM!
Ð ÑеÑение пÑоÑеÑÑа ÑазÑабоÑки Ñ Ð½Ð°Ñ Ð¼Ð¾Ð³ÑÑ Ð²Ð¾Ð·Ð½Ð¸ÐºÐ½ÑÑÑ Ð¸Ð´ÐµÐ¸ о новÑÑ Ð²ÑÑÑоеннÑÑ Ð¼ÐµÑÐ¾Ð´Ð°Ñ , коÑоÑÑе нам Ñ Ð¾ÑелоÑÑ Ð±Ñ Ð¸Ð¼ÐµÑÑ, и иÑкÑÑение добавиÑÑ Ð¸Ñ Ð²Ð¾ вÑÑÑоеннÑе пÑоÑоÑипÑ. ÐÑо Ð¿Ð»Ð¾Ñ Ð°Ñ Ð¸Ð´ÐµÑ.
ÐÑоÑоÑÐ¸Ð¿Ñ Ð³Ð»Ð¾Ð±Ð°Ð»ÑнÑ, поÑÑÐ¾Ð¼Ñ Ð¾ÑÐµÐ½Ñ Ð»ÐµÐ³ÐºÐ¾ могÑÑ Ð²Ð¾Ð·Ð½Ð¸ÐºÐ½ÑÑÑ ÐºÐ¾Ð½ÑликÑÑ. ÐÑли две библиоÑеки добавлÑÑÑ Ð¼ÐµÑод String.prototype.show, Ñо одна из ниÑ
пеÑепиÑÐµÑ Ð¼ÐµÑод дÑÑгой.
Так ÑÑо, в обÑем, изменение вÑÑÑоеннÑÑ Ð¿ÑоÑоÑипов ÑÑиÑаеÑÑÑ Ð¿Ð»Ð¾Ñ Ð¾Ð¹ идеей.
Ð ÑовÑеменном пÑогÑаммиÑовании еÑÑÑ ÑолÑко один ÑлÑÑай, в коÑоÑом одобÑÑеÑÑÑ Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ðµ вÑÑÑоеннÑÑ Ð¿ÑоÑоÑипов. ÐÑо Ñоздание полиÑилов.
ÐолиÑил â ÑÑо ÑеÑмин, коÑоÑÑй ознаÑÐ°ÐµÑ ÑмÑлÑÑÐ¸Ñ Ð¼ÐµÑода, коÑоÑÑй ÑÑÑеÑÑвÑÐµÑ Ð² ÑпеÑиÑикаÑии JavaScript, но еÑÑ Ð½Ðµ поддеÑживаеÑÑÑ ÑекÑÑим движком JavaScript.
Тогда Ð¼Ñ Ð¼Ð¾Ð¶ÐµÐ¼ ÑеализоваÑÑ ÐµÐ³Ð¾ Ñами и добавиÑÑ Ð²Ð¾ вÑÑÑоеннÑй пÑоÑоÑип.
ÐапÑимеÑ:
if (!String.prototype.repeat) { // ÐÑли Ñакого меÑода неÑ
// добавлÑем его в пÑоÑоÑип
String.prototype.repeat = function(n) {
// повÑоÑиÑÑ ÑÑÑÐ¾ÐºÑ n Ñаз
// на Ñамом деле код должен бÑÑÑ Ð½ÐµÐ¼Ð½Ð¾Ð³Ð¾ более ÑложнÑм
// (полнÑй алгоÑиÑм можно найÑи в ÑпеÑиÑикаÑии)
// но даже неполнÑй полиÑил заÑаÑÑÑÑ Ð´Ð¾ÑÑаÑоÑно Ñ
оÑÐ¾Ñ Ð´Ð»Ñ Ð¸ÑполÑзованиÑ
return new Array(n + 1).join(this);
};
}
alert( "La".repeat(3) ); // LaLaLa
ÐаимÑÑвование Ñ Ð¿ÑоÑоÑипов
Рглаве ÐекоÑаÑоÑÑ Ð¸ пеÑеадÑеÑаÑÐ¸Ñ Ð²Ñзова, call/apply Ð¼Ñ Ð³Ð¾Ð²Ð¾Ñили о заимÑÑвовании меÑодов.
ÐÑо когда Ð¼Ñ Ð±ÐµÑÑм меÑод из одного обÑекÑа и копиÑÑем его в дÑÑгой.
ÐекоÑоÑÑе меÑÐ¾Ð´Ñ Ð²ÑÑÑоеннÑÑ Ð¿ÑоÑоÑипов ÑаÑÑо одалживаÑÑ.
ÐапÑимеÑ, еÑли Ð¼Ñ ÑоздаÑм обÑекÑ, поÑ
ожий на маÑÑив (пÑевдомаÑÑив), Ð¼Ñ Ð¼Ð¾Ð¶ÐµÐ¼ ÑкопиÑоваÑÑ Ð½ÐµÐºÐ¾ÑоÑÑе меÑÐ¾Ð´Ñ Ð¸Ð· Array в ÑÑÐ¾Ñ Ð¾Ð±ÑекÑ.
ÐÑимеÑ:
let obj = {
0: "Hello",
1: "world!",
length: 2,
};
obj.join = Array.prototype.join;
alert( obj.join(',') ); // Hello,world!
ÐÑо ÑабоÑаеÑ, поÑÐ¾Ð¼Ñ ÑÑо Ð´Ð»Ñ Ð²Ð½ÑÑÑеннего алгоÑиÑма вÑÑÑоенного меÑода join Ð²Ð°Ð¶Ð½Ñ ÑолÑко коÑÑекÑноÑÑÑ Ð¸Ð½Ð´ÐµÐºÑов и ÑвойÑÑво length, он не пÑовеÑÑеÑ, ÑвлÑеÑÑÑ Ð»Ð¸ обÑÐµÐºÑ Ð½Ð° Ñамом деле маÑÑивом. Рмногие вÑÑÑоеннÑе меÑÐ¾Ð´Ñ ÑабоÑаÑÑ Ñак же.
ÐлÑÑеÑнаÑÐ¸Ð²Ð½Ð°Ñ Ð²Ð¾Ð·Ð¼Ð¾Ð¶Ð½Ð¾ÑÑÑ â Ð¼Ñ Ð¼Ð¾Ð¶ÐµÐ¼ ÑнаÑледоваÑÑ Ð¾Ñ Ð¼Ð°ÑÑива, ÑÑÑановив obj.__proto__ как Array.prototype, Ñаким обÑазом вÑе меÑÐ¾Ð´Ñ Array ÑÑанÑÑ Ð°Ð²ÑомаÑиÑеÑки доÑÑÑÐ¿Ð½Ñ Ð² obj.
Ðо ÑÑо бÑÐ´ÐµÑ Ð½ÐµÐ²Ð¾Ð·Ð¼Ð¾Ð¶Ð½Ð¾, еÑли obj Ñже наÑледÑÐµÑ Ð¾Ñ Ð´ÑÑгого обÑекÑа. ÐомниÑе, Ð¼Ñ Ð¼Ð¾Ð¶ÐµÐ¼ наÑледоваÑÑ ÑолÑко Ð¾Ñ Ð¾Ð´Ð½Ð¾Ð³Ð¾ обÑекÑа одновÑеменно.
ÐаимÑÑвование меÑодов â гибкий ÑпоÑоб, позволÑÑÑий ÑмеÑиваÑÑ ÑÑнкÑионалÑноÑÑÑ ÑазнÑÑ Ð¾Ð±ÑекÑов по Ð½ÐµÐ¾Ð±Ñ Ð¾Ð´Ð¸Ð¼Ð¾ÑÑи.
ÐÑого
- ÐÑе вÑÑÑоеннÑе обÑекÑÑ ÑледÑÑÑ Ð¾Ð´Ð½Ð¾Ð¼Ñ ÑаблонÑ:
- ÐеÑÐ¾Ð´Ñ Ñ
ÑанÑÑÑÑ Ð² пÑоÑоÑипаÑ
(
Array.prototype,Object.prototype,Date.prototypeи Ñ.д.). - Сами обÑекÑÑ Ñ ÑанÑÑ ÑолÑко даннÑе (ÑлеменÑÑ Ð¼Ð°ÑÑивов, ÑвойÑÑва обÑекÑов, даÑÑ).
- ÐеÑÐ¾Ð´Ñ Ñ
ÑанÑÑÑÑ Ð² пÑоÑоÑипаÑ
(
- ÐÑимиÑÐ¸Ð²Ñ Ñакже Ñ
ÑанÑÑ Ñвои меÑÐ¾Ð´Ñ Ð² пÑоÑоÑипаÑ
обÑекÑов-обÑÑÑок:
Number.prototype,String.prototype,Boolean.prototype. ТолÑко Ñ Ð·Ð½Ð°ÑенийundefinedиnullÐ½ÐµÑ Ð¾Ð±ÑекÑов-обÑÑÑок. - ÐÑÑÑоеннÑе пÑоÑоÑÐ¸Ð¿Ñ Ð¼Ð¾Ð³ÑÑ Ð±ÑÑÑ Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ñ Ð¸Ð»Ð¸ Ð´Ð¾Ð¿Ð¾Ð»Ð½ÐµÐ½Ñ Ð½Ð¾Ð²Ñми меÑодами. Ðо не ÑекомендÑеÑÑÑ Ð¼ÐµÐ½ÑÑÑ Ð¸Ñ . ÐдинÑÑÐ²ÐµÐ½Ð½Ð°Ñ Ð´Ð¾Ð¿ÑÑÑÐ¸Ð¼Ð°Ñ Ð¿ÑиÑина â ÑÑо добавление нового меÑода из ÑÑандаÑÑа, коÑоÑÑй еÑÑ Ð½Ðµ поддеÑживаеÑÑÑ Ð´Ð²Ð¸Ð¶ÐºÐ¾Ð¼ JavaScript.
ÐомменÑаÑии
<code>, Ð´Ð»Ñ Ð½ÐµÑколÑÐºÐ¸Ñ ÑÑÑок кода — Ñег<pre>, еÑли болÑÑе 10 ÑÑÑок — ÑÑÑÐ»ÐºÑ Ð½Ð° пеÑоÑниÑÑ (plnkr, JSBin, codepenâ¦)