10 întrebări privind interviul javascript al unui programator, fiecare ar trebui să răspundă, biblioteca

1. moștenire prototipică (de asemenea: prototipuri, referințe de obiecte)

2. Programare funcțională (de asemenea: închideri, funcții de primă clasă, lambda)

Nu aveți nicio idee despre paradigme, nu menționați OOP prototipic sau programare funcțională.

Programarea funcțională implică calcularea funcțiilor matematice, evitarea stărilor comune și a datelor variabile. Lisp (specificat în 1958) este unul dintre primele limbi de programare funcționale și este puternic inspirat de lambda calculi. Lisp și limbile similare sunt utilizate pe scară largă pentru această zi.

1. Funcții pure / puritatea funcțiilor

2. Evitarea efectelor secundare

3. Compoziție simplă a funcțiilor

4. Exemple de limbi funcționale: Lisp, ML, Haskell, Erlang, Clojure, Elm, F Sharp, OCaml etc.

5. Funcții care susțin programarea funcțională: funcții de primă clasă, funcții de ordin superior, funcții ca argumente / valori

1. Lipsa mențiunii funcțiilor curate / evitarea efectelor secundare

2. Nu dați exemple de limbi funcționale

Moștenirea claselor: instanțele sunt moștenite din clase, se creează relații de subclasă (clasificarea ierarhică a clasei). Instanțele sunt implementate prin intermediul constructorului de funcții, prin noul descriptor. O instanță a unei clase nu poate conține un descriptor de clasă care începe cu ES6.

Moștenirea prototipică: instanțele sunt moștenite direct din alte obiecte, implementate prin fabrici sau Object.create () și instanțele pot fi compuse din mai multe obiecte diferite pentru a simplifica moștenirea selectivă. Prototipul de moștenire este mai simplu și mai flexibil decât moștenirea de clasă.

1. Clase: legături strânse, ierarhie

2. Prototipuri: moștenire concatenară, delegare, moștenire funcțională, compoziție

Nu evidențiați avantajele moștenirii prototipului asupra clasei

Avantajele PLO: un concept ușor de înțeles al obiectelor și metodelor de apelare. PLO încearcă să folosească stilul imperativ, mai degrabă decât declarativ, care este citit ca un set direct de instrucțiuni de mașină.

Contra pentru POR: de regulă, există o dependență de stările generale. Obiectele și comportamentul lor sunt legate de o entitate la care poate fi accesat un număr de funcții într-o ordine nedefinită, ceea ce poate conduce la un comportament imprevizibil, de exemplu, starea rasei.

Avantajele PL: se folosește o paradigmă funcțională care evită stările comune și efectele nedorite, elimină erorile posibile din cauza funcțiilor concurente. Datorită unor caracteristici precum programarea implicită, funcțiile sunt, de obicei, radical simplificate și ușor reconstruite pentru a fi mai ușor, comparativ cu reutilizarea codurilor OOP.

Calculele care utilizează funcții pure sunt reduse cu ușurință la mai mulți procesori sau clustere computerizate distribuite fără teama de a lupta pentru resurse.

FP contra: exploatarea excesivă a abordărilor funcționale, cum ar fi programarea implicită, poate duce la o scădere a lizibilității codului, deoarece codul final se dovedește a fi mai abstract, mai concis și mai puțin concret.

Mai des, oamenii sunt mai familiarizați cu PPO și cu abordarea imperativă, astfel încât unele idiomuri comune ale programării funcționale pot provoca dificultăți pentru începători.

1. Probleme ale condițiilor generale, comportament nedorit

2. Posibilitățile OP pentru simplificarea radicală a codului de program

3. Dificultate în studiu

4. Efectele adverse și impactul acestora asupra fiabilității programului

5. Complexitatea schimbării și fragilitatea generală a bazei de cod OO față de cea a stilului funcțional

Să nu mai vorbim de neajunsurile uneia dintre abordări - oricine a întâlnit unul dintre ei știe despre câteva sau două dezavantaje

Problema cu trucurile. Răspunsul corect nu este niciodată. Compoziția este o abordare mai simplă și mai flexibilă decât moștenirea claselor.

"... compoziția obiectelor este mai bună decât moștenirea claselor"

Există mai mult de un tip de moștenire prototip:

1. Delegația (lanț de prototipuri)

2. Concatenarea (mixine, Object.assign ())

3. moștenire funcțională (nu trebuie confundată cu programarea funcțională, funcția este utilizată pentru a crea o închidere pentru închidere / încapsulare)

1. În situațiile în care modulele sau programarea funcțională nu oferă o soluție evidentă

2. Când aveți nevoie să asamblați un obiect din mai multe surse

3. În orice caz, atunci când trebuie să aplicați moștenirea

1. Nu știu când se utilizează prototipurile

2. Nu știți despre mixine sau Object.assign ()

Acesta este un citat din cartea "Modele de design: Elemente de software reutilizabil orientat pe obiecte". Reutilizarea codului ar trebui realizată prin asamblarea unor unități mici de funcționalitate într-un obiect nou, mai degrabă decât prin moștenirea claselor și crearea de ierarhii.

1. Evitarea moștenirii și a legăturilor strânse

Nu menționați nici una dintre problemele menționate mai sus. Nu explicați diferența dintre compoziție și moștenire sau nu reușiți să spuneți despre beneficiile compoziției.

Comunicarea de date în două direcții implică faptul că câmpurile de interfață sunt legate în mod dinamic de modelul de date, adică când se schimbă câmpurile de interfață, modifică modelul și invers.

Un flux de date unidirecțional înseamnă că numai modelul este sursa adevărului. Modificările din interfața de pornire a mesajelor semnalează utilizatorului despre intenția modelului (sau "magazin" în termeni de React). Ideea este că datele merg întotdeauna într-o singură direcție, ceea ce facilitează înțelegerea.

Fluxurile de date cu sens unic sunt deterministe, în timp ce legarea în două sensuri poate provoca efecte nedorite, care sunt mai greu de urmărit și de înțeles.

1. Reactul este un nou exemplu canonic al unui flux de date unidirecțional, așadar menționarea React va fi o idee bună. Cycle.js este o altă implementare populară a unui flux de date unidirecțional.

2. Angular este un cadru popular care folosește legarea bidirecțională.

Eșecul de a înțelege aceste concepte, incapacitatea de a explica diferența dintre ele.

Arhitectura monolitică înseamnă că aplicația dvs. este scrisă ca un singur bloc de cod coerent, ale cărui componente sunt proiectate să colaboreze și să utilizeze resurse partajate.

Abordarea microservicii implică faptul că aplicația este alcătuită din numeroase aplicații independente mici care pot funcționa cu propriile resurse și potențial pe un număr mare de mașini individuale.

Avantajele arhitecturii monolitice: Principalul avantaj al unei arhitecturi monolitice este că majoritatea aplicațiilor au de obicei multe probleme comune, cum ar fi logarea, limitarea vitezei și necesitatea funcțiilor de securitate - sunt mai ușor de rezolvat pentru fiecare componentă într-o singură aplicație.

Consumul de aplicare monolitică: deoarece toate componentele sunt strâns legate între ele, pe măsură ce se dezvoltă aplicația, devine mai greu de înțeles, apar multe dependențe și efecte secundare nereușite.

Proiecte ale microservicii: microservicii sunt, de obicei, mai bine organizate, deoarece fiecare componentă își îndeplinește sarcina și funcționează independent de fiecare componentă. O aplicație bazată pe componente separate este, de asemenea, mai ușor de reconfigurat și modificat.

Minusurile microservicii: atunci când creați un microserviciu nou, pot exista multe probleme bruște care nu au fost așteptate în proiectare. Pentru o aplicație monolitică, puteți folosi middleware pentru a rezolva diferite probleme de la capăt la celălalt, fără prea multă muncă.

Cu o arhitectură de micro-servicii, fie vor fi necesare fie cheltuielile generale pentru module individuale pentru fiecare problemă transversală, fie este necesar să le încapsuleze la un alt nivel de serviciu prin care trece tot traficul.

La urma urmei, chiar și arhitecturile monolitice tind să direcționeze traficul printr-un nivel de serviciu extern, dar cu o arhitectură monolitică, puteți amâna costurile acestei lucrări până când proiectul devine mai matur.

Microservicii sunt deseori implementate în propriile lor mașini sau containere virtuale, ceea ce duce la o creștere rapidă a numărului de conflicte asupra resurselor virtuale.

1. În ciuda costului inițial ridicat, microservicii beneficiază pe termen lung datorită scalării mai bune

2. Diferențele practice între microservicii și aplicațiile monolitice

1. Necunoașterea diferențelor în arhitectură

2. Necunoașterea dezavantajelor microservicii

3. Subestimați avantajele micro-serviciilor scalabile

Programarea sincronă înseamnă că, cu excepția condițiilor și apelurilor pentru funcții, codul este executat secvențial de sus în jos, persistând pe sarcini lungi, cum ar fi cererile de rețea și citirea / scrierea de pe disc.

Programarea asincronă implică faptul că atunci când este necesară o operație de blocare, cererea este trimisă și codul continuă să funcționeze fără blocare până când rezultatul este așteptat. Când răspunsul este gata, se declanșează o întrerupere, aceasta declanșează procedura de tratare a evenimentului și firul de control continuă. Astfel, un flux de programe poate procesa o serie de operații paralele.

Interfețele utilizator sunt în mod inerent asincrone, de cele mai multe ori petrec așteptând intrarea utilizatorilor pentru a întrerupe buclele și a porni manualul.

Node.js este în mod implicit asincron, de fapt, serverul petrece tot timpul într-o buclă, așteptând o solicitare de rețea.

1. Semnificația blocărilor, impactul asupra performanței

2. Înțelegerea operatorilor și motivul pentru care aceștia sunt importanți pentru interfețe

1. Nerespectarea termenilor de sincronizare și asincronie

2. Incapacitatea de a determina impactul asupra productivității