Loading...

Камтылган прототиптер

Камтылган прототиптер

 

Менчик "prototype"JavaScript тилинин өзүндө кеңири колдонулат. Бардык орнотулган конструктор функциялары аны колдонот.

"prototype"Биз адегенде майда-чүйдөсүнө чейин карап чыгабыз, анан аны орнотулган объекттерге жаңы функцияларды кошуу үчүн колдонобуз .

Объект.прототип

Келгиле, бош объект чыгаралы:

@A@let obj = {};
alert( obj ); // "[object Object]" ?@A@

Сапты түзгөн код кайда "[object Object]"? Бул камтылган ыкма toString, бирок ал кайда? objал бош!

…Бирок, кыска белги obj = {}менен бирдей, obj = new Object()бул жерде Objectөзүнүн менчиги бар объекттер үчүн орнотулган конструктор функциясы бар prototype, ал методу toStringжана башкалары бар чоң объектти билдирет.

Бул жерде эмне болот:

 

Объект чакырылганда new Object()(же объект литерал аркылуу түзүлгөн {...}), ал объекттин касиети биз мурунку бөлүмдө талкуулаган эрежелерге ылайык [[Prototype]]коюлат :Object.prototype

Ошентип, качан чакырылса obj.toString(), ыкма дан алынат Object.prototype.

Биз муну сынай алабыз:

@A@let obj = {};

alert(obj.__proto__ === Object.prototype); // true
// obj.toString === obj.__proto__.toString === Object.prototype.toString@A@

Object.prototypeЖогорудагы прототип чынжырында мындан ары менчик жок экенине көңүл буруңуз [[Prototype]]:

 
@A@alert(Object.prototype.__proto__); // null@A@

Башка орнотулган прототиптер

Башка орнотулган объекттер, мисалы ArrayDateFunctionжана башкалар да өз ыкмаларын прототиптерде сакташат.

Мисалы, массивди түзүүдө [1, 2, 3]массивдин конструктору ички түрдө колдонулат Array. Ошентип, ал массивдин прототиби болуп калат Array.prototype, аны өзүнүн ыкмалары менен камсыз кылат. Бул эстутумду натыйжалуу пайдаланууга мүмкүндүк берет.

Спецификацияга ылайык, орнотулган прототип иерархиясынын жогору жагында Object.prototype. Ошондон улам кээде «бардыгы предметтен мурастайт» деп айтылат.

Бул жерде толугураак сүрөт (үч камтылган объект үчүн):

Келгиле, прототиптерди карап көрөлү:

@A@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@A@

Прототиптердеги кээ бир методдор бири-бирине дал келиши мүмкүн, мисалы, алардын Array.prototypeөз ыкмасы бар toString, ал массивдин элементтерин үтүр менен ажыратылган:

@A@let arr = [1, 2, 3]
alert(arr); // 1,2,3 <-- результат Array.prototype.toString@A@

Мурда көргөндөй, u Object.prototypeөзүнүн ыкмасына ээ toString, бирок ал Array.prototypeпрототип чынжырында жакыныраак болгондуктан, массивдердин варианты алынат:

Иштеп чыгуучунун консолу сыяктуу браузер куралдарында мурастоо чынжырын көрө аласыз ( console.dirкурган объекттер үчүн колдонуу керек болушу мүмкүн):

Башка орнотулган объекттер да ушундай эле түзүлүштө. Жада калса функциялар да орнотулган конструктор объекттери Functionжана алардын бардык ыкмалары ( callapplyжана башкалар) Function.prototype. Функциялардын да өз ыкмасы бар toString.

@A@function f() {}

alert(f.__proto__ == Function.prototype); // true
alert(f.__proto__.__proto__ == Object.prototype); // true, наследует от Object@A@

Примитивдер

Эң кыйын бөлүгү саптар, сандар жана логикалык саптар менен болот.

Биз эстегендей, алар объектилер эмес. Бирок, эгерде биз алардын касиеттерине жетүүгө аракет кылсак, анда орнотулган конструкторлордун жардамы менен убактылуу орогуч объекти түзүлөт Stringжана методдорун камсыздайт, анан жок болот.NumberBoolean

Бул объекттер биз үчүн көрүнбөй жаратылган жана көпчүлүк кыймылдаткычтар бул процессти оптималдаштыруу, бирок спецификация аны ушундай сүрөттөйт. String.prototypeБул объекттердин ыкмалары, ошондой эле , Number.prototypeжана катары жеткиликтүү прототиптерде бар Boolean.prototype.

Маанилер nullжана undefinedорогуч объекттери жок

Өзгөчө маанилери nullжана undefinedжалгыз турат. Алардын орогуч объекттери жок, ошондуктан методдор жана касиеттер аларга жеткиликтүү эмес. Алардын да тиешелүү прототиптери жок.

Inline прототиптерин өзгөртүү

Камтылган прототиптерди өзгөртүүгө болот. Мисалы, эгер сиз ыкманы -га кошсоңуз String.prototype, ыкма бардык саптар үчүн жеткиликтүү болот:

 
 
@A@String.prototype.show = function() {
  alert(this);
};

"BOOM!".show(); // BOOM!@A@

Иштеп чыгуу процессинде бизде жаңы орнотулган ыкмалар жөнүндө ойлорубуз жана аларды орнотулган прототиптерге кошуу азгырыгы болушу мүмкүн. Бул жаман идея.

Маанилүү:

Прототиптер глобалдуу, ошондуктан чыр-чатактар ​​оңой эле пайда болушу мүмкүн. Эгерде эки китепкана бир методду кошсо String.prototype.show, алардын бири экинчисинин ыкмасынын үстүнөн жазат.

Ошентип, жалпысынан, орнотулган прототиптерди өзгөртүү жаман идея болуп эсептелет.

Заманбап программалоодо, орнотулган прототиптерди өзгөртүүгө алгылыктуу болгон бир гана учур бар. Бул polyfills түзүү болуп саналат.

Polyfill бул JavaScript спецификациясында бар, бирок учурдагы JavaScript кыймылдаткычы тарабынан колдоого алынбаган ыкманы эмуляциялоону билдирген термин.

Андан кийин биз аны өзүбүз ишке ашырып, орнотулган прототипке кошо алабыз.

Мисалы:

@A@if (!String.prototype.repeat) { // Если такого метода нет
  // добавляем его в прототип

  String.prototype.repeat = function(n) {
    // повторить строку n раз

    // на самом деле код должен быть немного более сложным
    // (полный алгоритм можно найти в спецификации)
    // но даже неполный полифил зачастую достаточно хорош для использования
    return new Array(n + 1).join(this);
  };
}

alert( "La".repeat(3) ); // LaLaLa@A@

Прототиптерден карыз алуу

Бөлүмдө Decorators жана Чалууларды багыттоо, чалуу/колдонуу, биз карыз алуу ыкмалары жөнүндө сүйлөштүк.

Бул ыкманы бир объекттен алып, экинчисине көчүрүү.

Кээ бир орнотулган прототип ыкмалары көбүнчө карызга алынат.

Мисалы, массив сымал объектти (псевдо-массив) түзсөк, Arrayбул объектке кээ бир методдорду көчүрө алабыз.

Мисал:

@A@let obj = {
  0: "Hello",
  1: "world!",
  length: 2,
};

obj.join = Array.prototype.join;

alert( obj.join(',') ); // Hello,world!@A@

Бул иштейт, анткени ички ыкманын ички алгоритми joinиндекстердин жана касиеттин тууралыгына гана кам көрөт length, объект чындыгында массив экендигин текшербейт. Жана көптөгөн орнотулган ыкмалар бирдей иштейт.

obj.__proto__Альтернативдик мүмкүнчүлүк катары орнотуу менен массивден мураска алабыз Array.prototype, андыктан бардык ыкмалар Arrayавтоматтык түрдө жеткиликтүү болот obj.

objБирок, эгерде ал башка объекттен мураска калса, бул мүмкүн болбойт . Эсиңизде болсун, биз бир эле учурда бир гана объекттен мурас ала алабыз.

Карыз алуу ыкмалары зарыл болгон ар кандай объекттердин функционалдуулугун аралаштыруунун ийкемдүү жолу.

Бардыгы

  • Бардык орнотулган объекттер бирдей үлгү боюнча:
    • Методдор прототиптерде сакталат ( Array.prototypeObject.prototypeDate.prototypeж.б.).
    • Объекттердин өздөрү гана маалыматтарды (массив элементтери, объекттин касиеттери, даталар) сакташат.
  • Примитивдер өз ыкмаларын орогуч объекттеринин прототиптеринде да сакташат: Number.prototypeString.prototypeBoolean.prototype. Болгону баалуулуктар undefinedжана nullорогуч объекттери жок.
  • Камтылган прототиптер жаңы ыкмалар менен өзгөртүлүшү же толукталышы мүмкүн. Бирок аларды өзгөртүү сунушталбайт. Жалгыз жүйөлүү себеп - JavaScript кыймылдаткычы тарабынан колдоого алынбаган стандарттан жаңы ыкманы кошуу.

Tasks

маанилүүлүгү: 5

Прототиптеги бардык функцияларга defer(ms)функцияларды msмиллисекунддан кийин чакырган ыкманы кошуңуз.

Андан кийин, бул код иштеши керек:

@A@function f() {
  alert("Hello!");
}

f.defer(1000); // выведет "Hello!" через 1 секунду@A@
чечим
маанилүүлүгү: 4

Прототиптеги бардык функцияларга методду кошуңуз defer(ms), ал функциянын чакырылышын миллисекундга кечиктирген оромону кайтарат ms.

Мисалы, ал төмөнкүдөй иштеши керек:

@A@function f(a, b) {
  alert( a + b );
}

f.defer(1000)(1, 2); // выведет 3 через 1 секунду.@A@

Аргументтер баштапкы функцияга туура өтүшү керек экенин эске алыңыз.