Објашњено ЈаваСцрипт прототипско наслеђивање коришћењем ЦСС-а

Прототипско наслеђивање је вероватно најмање разумљиви аспект ЈаваСцрипт-а. Па добра вест је да ако разумете како ЦСС ради, можете да разумете и како ЈаваСцрипт прототипи раде.

Лепо је када је нешто једноставно у стању да објасни нешто наизглед сложено, аналогија - као што пиледрифер забија стуб дубоко у земљу, аналогија одводи тачку кући.

Ја сам љубитељ аналогија, аналогифил.

Идемо.

Прототипови у ЦСС дугмадима

Видите два дугмета горе? Дизајнираћемо их у ЦСС-у.

Кренимо и брзо напишите стилове за ова два дугмета, почев од .btn

.btn { min-width: 135px; min-height: 45px; font-family: ‘Avenir Next’, sans-serif; font-size: 18px; font-weight: bold; letter-spacing: 1.3px; color: #4D815B; background-color: #FFF; border: 2px solid #4D815B; border-radius: 4px; padding: 5px 20px; cursor: pointer;}

То је прилично једноставан блок ЦСС кода.

Сада пређимо на стилове за .btn-solid

.btn-solid { min-width: 135px; min-height: 45px; font-family: ‘Avenir Next’, sans-serif; font-size: 18px; font-weight: bold; letter-spacing: 1.3px; color: #FFF; background-color: #4D815B; border: 2px solid #4D815B; border-radius: 4px; padding: 5px 20px; cursor: pointer;}

Као што сте већ могли приметити, осим смелих, сви остали стилови у .btn-solidњима су идентични онима у .btn. А ако сте упознати са Сассом, можда знате да се .btn-solidстилови у САСС могу преписати овако:

.btn-solid { @extend .btn; color: #FFF; background-color: #4D815B;}

Као што видите, .btn-solidнаслеђује стилове из .btn, а затим замењује неке од њих (фонт и боју позадине) да би се креирао. Што нас наводи на закључак да.btn-solidје специјализована верзија .btn. Или, другим речима, .btn-solidније .btnали са различитим бојама фонт и позадини. То има смисла, зар не? Али сачекајте има још.

Рецимо да желите да направите већи дугме, .btn-lg. Користићемо .btnкао прототип за испоруку основних стилова. Затим ћемо, слично ономе како смо модификовали боје позадине и фонта .btn-solid, измијенити својство величине фонта на већу вриједност како бисмо створили веће дугме.

Обе верзије .btn-lgи .btn-solidсу специјализоване верзије .btn. .btnиспоручује основне стилове .btn-lgи .btn-solidкоји затим преписују неке од основних стилова да би се сами креирали. То нам говори да се једно дугме за које одлучимо - .btnу нашем случају - може користити као добављач основних стилова за више ставки.

У овом одељку покушали смо да дефинишемо концепт прототипова за ЦСС дугмад. Прототип је ентитет који пружа основне стилове, који се могу проширити тако да креирају различите инстанце дугмади. Ова дефиниција прототипа врло је блиска ономе што прототипи заправо значе у програмском смислу.

У програмском смислу, прототип је објекат који даје основно понашање другом објекту. Други објекат затим проширује ово основно понашање да би формирао сопствену специјализацију. Погледајмо у следећем одељку како се наше знање о прототиповима у ЦСС дугмадима пресликава на ЈаваСцрипт.

Прототипови у ЈаваСцрипт-у

Размотрите следећи ЈаваСцрипт објекат:

let obj = { a: 1};

Знамо да се вредности aможе приступити obj.a, с обзиром да aје то очигледно својство obj. Али има још тога, можете и да позовете obj.hasOwnProperty('a')да бисте проверили да ли objзаиста има својство са именом a.

Сачекајте секунду - према ономе што можемо видети, на њој није дефинисано objниједно својство које се назива hasOwnProperty. Одакле је hasOwnPropertyдошло? Да бисмо одговорили на ово питање, мораћемо да се вратимо на дугмад која смо управо завршили.

.btn-solidсамо има дефинисане боје позадине и фонта. Одакле долази, на пример border-radius,? Знамо да .btn-solidје специјализација .btn, тако да се види да .btn-solidје све стилове као border-radius, width, height, и paddingиз .btn. Да ли би могло бити исто са obj?

Баш као .btn-solidи .btn-lgда њихове базе стилова из .btn, objили било који други ЈаваСцрипт објекат за који материја добијају базу понашање из другог објекта -Object.prototype . И ово Object.prototypeје hasOwnPropertyдефинисало на њему. Као резултат, ово даје objприступ hasOwnPropertyметоди - баш као што .btn-solidје имао приступ .btnи border-radiusсвојству.

Ово - објекат (обј) који наслеђује своја својства и базно понашање од другог објекта (Објецт.прототипе) - је оно што називамо прототипским наследством. Приметите да није classукључен у међусобну игру.

Стварни унутрашњи рад ЈаваСцрипт прототипова и наших ЦСС „прототипова“ се много разликује. Али у сврху наше аналогије, можемо занемарити њихов рад иза кулиса.

Object.prototypeније једини прототип доступан у ЈаваСцрипт-у. Ту је Array.prototype, Function.prototype, Number.prototypeи неколико других. Посао свих ових прототипова је пружање основних поступака или корисних метода њиховим инстанцама.

На пример, сваки низ проглашен ЈаваСцрипт има приступ .push, .sort, .forEach, и .mapсамо због прототипал повезивања. И из истог разлога свака функција има приступ .call, .apply, .bind.

Прототипови и прототипско наслеђивање нису специфични за ЈаваСцрипт. Они су конструкција коју ЈаваСцрипт користи интерно и омогућава нам да га користимо у сопственим програмима. Пре него што погледамо како тачно то можемо да урадимо, морамо да схватимо шта је прототипско ланчење.

Прототипал Цхаининг

Једном ћемо се морати вратити на аналогију дугмади. Рецимо да желим да направим велико чврсто дугме .btn-solid-lg:

Основне стилове које .btn-solid-lgиспоручује .btn-solidи .btn-solid-lgпреписује својство величине фонта да би се креирало.

Ипак погледајте детаљније. .btn-solidна њему су дефинисана само два стила - боја позадине и боја (фонт). То значи .btn-solid-lgда за себе има само 3 стила: боју позадине, боју и величину фонта. Где су width, height, border-radiusдолазе из?

Ок, ево наговештаја:

Ако сте желели да направите изузетно велико дугме .btn-solid-xlg, могли бисте то да учините .btn-solid-lgкао прототип. Али како се све ово пресликава на ЈаваСцрипт?

У ЈаваСцрипт-у вам је дозвољено да креирате и прототипове ланаца. Једном када ово схватите, откључате читав низ алата за писање невероватно моћног кода. Да, невероватно моћан .

Погледајмо како функционишу ланци прототипа у ЈаваСцрипт-у.

Сећате се објекта који смо креирали у претходном одељку? Ону коју смо пажљиво именовали obj? Да ли сте знали да са objпрототипом можете створити онолико објеката колико желите ?

Object.createомогућава вам стварање новог објекта од наведеног прототипа објекта. То значи да можете да креирате још један објекат obj2, чији је objпрви прототип:

let obj2 = Object.create(obj);
// Add a property 'b' to obj2obj2.b = 2;

Ако сте до сада пратили, требали бисте схватити да иако на њему obj2није aдефинисано својство , то console.log(obj2.a)неће резултирати грешком, већ 1пријављивањем на конзолу. Некако овако:

Када obj2тражи a, прво претражује своја својства. Ако не може да пронађе одговарајуће својство, тражи његов прототип (обј), где га коначно проналази a. Ако такав је био случај да још увек не могу да пронађу a, потрага ће се наставити у ланцу прототип док не дође до задњег везу, Object.prototype.

С друге стране, ако aје дефинисано obj2, надјачало би све друге aс ако би било дефинисано на било ком од његових прототипова. Слично томе како .btn-solidзаобишла .btn'с и својства.color background-colorТо се назива сенком имовине .

Али шта је са дужином ланца прототипа? Постоји ли ограничење?

Не постоји ограничење дужине ланца прототипа. Такође нема ограничења за гранање. То значи да можете направити више инстанци са Object.prototype, objили obj2као прототип.

Па како ће вам ово ново знање о прототиповима и прототипском ланцувању помоћи да напишете бољи код?

Писање бољег кода са прототиповима

Циљ овог чланка био је да вам објасни шта су прототипови и како функционише прототипско наследство. Надам се да сам успео у овоме.

За овај последњи одељак, дозволићу себи да се мало бунцам. Надам се да вам не смета.

Ако погледате ЈаваСцрипт код доступан на мрежи - било у пројектима отвореног кода на Гитхуб-у или у оловкама Цодепен-а - открићете да већина њих користи образац конструктора за стварање објеката.

function Circle(radius) { this.radius = radius;}
Circle.prototype.area = function() { return Math.PI * this.radius * this.radius;}
// Constructor pattern for creating new objectslet circ = new Circle(5);

Узорак конструктора изгледа као класа. У раним данима, када је ЈаваСцрипт био далеко мање популаран од онога што је данас, newкључна реч је додата као маркетиншка стратегија.

Ова индиректност је имала за циљ да ЈаваСцрипт учини класичнијим обученим програмерима познатијим. Иако је дискутабилно колико је успео у томе, ненамерно је такође прикрио праву прототипну природу језика.

Реалност је таква да, иако конструктори изгледају као класе, они се уопште не понашају као класе. У ЈаваСцрипт-у постоје објекти и објекти који се протежу од других објеката. Конструктори и часови никада не долазе у обзир. Узорак конструктора непотребно компликује ствари, пуно се тога дешава иза кулиса.

Преклињем вас - сада када добро разумете прототипове - да престанете да користите образац конструктора.

Зашто то не учинити уместо тога?

let Circle = { create(radius) { // Creating prototypal linkage using Object.create let obj = Object.create(this); obj.radius = radius; return obj; }, area() { return Math.PI * this.radius * this.radius; }};
let circ = Circle.create(5);

Надам се да вам је ова аналогија помогла да боље разумете прототипове, прототипско уланчавање и наслеђивање прототипа Object.create. Сада можете писати бољи код и престати користити претенциозне часове.

Хвала за читање! Ако је мој чланак био користан, кликните на зелено срце испод да бисте га препоручили и поделите га са колегама програмерима.

А за даље читање, погледајте Аадит Схах Зашто је прототипско наслеђе важно.

Тражите још? Редовно објављујем на свом блогу на насхваил.ме. Видимо се тамо, добар вам је!