JavaScript je službeni jezik svih modernih web preglednika. Kao takva, pitanja o JavaScriptu pojavljuju se u svim vrstama intervjua za programere.
Ovaj članak ne govori o najnovijim JavaScript knjižnicama, uobičajenim razvojnim praksama ili bilo kojoj od novih ES6 funkcija. Umjesto toga, riječ je o 3 stvari koje se obično pojave u intervjuima kada se raspravlja o JavaScriptu. I meni su postavljana ova pitanja, a prijatelji su mi rekli da su i njih pitali.
Naravno, ovo nisu jedine 3 stvari koje biste trebali proučiti prije JavaScript intervjua - postoji mnoštvo načina na koje se možete bolje pripremiti za predstojeći intervju - ali u nastavku su navedena tri pitanja koja anketar može postaviti kako bi procijenio koliko dobro znate i razumijete jezik JavaScript i DOM.
Pa krenimo! Imajte na umu da ćemo u donjim primjerima koristiti vanilin JavaScript, jer će vaš ispitivač obično htjeti vidjeti koliko dobro razumijete JavaScript i DOM bez pomoći knjižnica poput jQueryja.
Pitanje br. 1: Delegiranje događaja
Kada gradite aplikaciju, ponekad ćete trebati prikačiti slušatelje događaja na gumbe, tekst ili slike na stranici kako biste izvršili neku radnju kada korisnik stupi u interakciju s elementom.
Ako za primjer uzmemo jednostavan popis zadataka, ispitivač vam može reći da želi da se akcija dogodi kada korisnik klikne na jednu od stavki popisa. I žele da ovu funkcionalnost implementirate u JavaScript pretpostavljajući sljedeći HTML kôd:
- Walk the dog
- Pay bills
- Make dinner
- Code for one hour
Možda biste željeli učiniti nešto poput sljedećeg kako biste elemente dodali slušateljima događaja:
document.addEventListener('DOMContentLoaded', function() { let app = document.getElementById('todo-app'); let items = app.getElementsByClassName('item'); // attach event listener to each item for (let item of items) { item.addEventListener('click', function() { alert('you clicked on item: ' + item.innerHTML); }); } });
Iako to tehnički funkcionira, problem je u tome što slušalicu događaja pridajete svakoj pojedinačnoj stavci. To je u redu za 4 elementa, ali što ako netko na svoj popis zadataka doda 10.000 predmeta (možda ima puno stvari za obaviti)? Tada će vaša funkcija stvoriti 10 000 zasebnih slušatelja događaja i pridružiti svakog od njih na DOM-u. Ovo nije vrlo učinkovito.
U intervjuu bi bilo najbolje prvo ispitivača pitati koji je maksimalan broj elemenata koje korisnik može unijeti. Na primjer, ako nikad ne može biti veće od 10, tada bi gornji kod dobro funkcionirao. Ali ako nema ograničenja na broj stavki koje korisnik može unijeti, tada biste željeli koristiti učinkovitije rješenje.
Ako bi vaša aplikacija mogla završiti sa stotinama slušatelja događaja, učinkovitije bi rješenje bilo zapravo spojiti jedan slušatelj događaja na cijeli spremnik, a zatim moći pristupiti svakoj stavci kad se na nju stvarno klikne. To se naziva delegiranje događaja i mnogo je učinkovitije od pričvršćivanja zasebnih voditelja događaja.
Evo koda za delegiranje događaja:
document.addEventListener('DOMContentLoaded', function() { let app = document.getElementById('todo-app'); // attach event listener to whole container app.addEventListener('click', function(e) { if (e.target && e.target.nodeName === 'LI') { let item = e.target; alert('you clicked on item: ' + item.innerHTML); } }); });
Pitanje br. 2: Korištenje zatvarača unutar petlje
Zatvaranja se ponekad prikazuju u intervjuu kako bi anketar mogao procijeniti koliko ste upoznati s jezikom i znate li kada treba primijeniti zatvaranje.
Zatvaranje je u osnovi kada unutarnja funkcija ima pristup varijablama izvan svog opsega. Zatvarači se mogu koristiti za stvari poput uvođenja privatnosti i stvaranja tvornica funkcija. Uobičajeno pitanje u vezi s upotrebom zatvarača je otprilike ovako:
Napišite funkciju koja će se petljati kroz popis cijelih brojeva i ispisati indeks svakog elementa nakon kašnjenja od 3 sekunde.
Uobičajena (netočna) implementacija koju sam vidio za ovaj problem izgleda otprilike ovako:
const arr = [10, 12, 15, 21]; for (var i = 0; i < arr.length; i++) { setTimeout(function() { console.log('The index of this number is: ' + i); }, 3000); }
Ako ovo pokrenete, vidjet ćete da se zapravo svaki put ispisuje 4 umjesto očekivanih 0, 1, 2, 3 nakon kašnjenja od 3 sekunde.
Da bi se ispravno prepoznalo zašto se to događa, bilo bi korisno razumjeti zašto se to događa u JavaScriptu, što je upravo ono što anketar pokušava testirati.
Razlog tome je što setTimeout
funkcija stvara funkciju (zatvaranje) koja ima pristup svom vanjskom opsegu, a to je petlja koja sadrži indeks i
. Nakon 3 sekunde funkcija se izvršava i ona ispisuje vrijednost i
, koja je na kraju petlje na 4, jer se kreće kroz 0, 1, 2, 3, 4 i petlja se konačno zaustavlja na 4.
Zapravo postoji nekoliko načina ispravnog pisanja funkcije za ovaj problem. Evo njih dvije:
const arr = [10, 12, 15, 21]; for (var i = 0; i < arr.length; i++) { // pass in the variable i so that each function // has access to the correct index setTimeout(function(i_local) { return function() { console.log('The index of this number is: ' + i_local); } }(i), 3000); }
const arr = [10, 12, 15, 21]; for (let i = 0; i < arr.length; i++) { // using the ES6 let syntax, it creates a new binding // every single time the function is called // read more here: //exploringjs.com/es6/ch_variables.html#sec_let-const-loop-heads setTimeout(function() { console.log('The index of this number is: ' + i); }, 3000); }
Pitanje br. 3: Otpuštanje
Postoje neki događaji u pregledniku koji se mogu aktivirati mnogo puta u kratkom vremenskom rasponu vrlo brzo, kao što je promjena veličine prozora ili pomicanje stranice. Ako na primjer pomaknete slušatelj događaja na događaj pomicanja prozora, a korisnik kontinuirano vrlo brzo pomiče stranicu, vaš se događaj može aktivirati tisuće puta u rasponu od 3 sekunde. To može uzrokovati ozbiljne probleme s izvedbom.
Ako u intervjuu razgovarate o izradi aplikacije, a pojave se događaji poput pomicanja, promjene veličine prozora ili pritiska tipke, obavezno spomenite otkazivanje i / ili regulaciju kao način za poboljšanje brzine i performansi stranice. Pravi primjer preuzet iz ovog gostujućeg posta na css-trikovima:
2011. godine na web stranici Twittera pojavio se problem: kada ste pomicali svoj Twitter feed, postalo je sporo i nije reagiralo. John Resig objavio je post na blogu o problemu u kojem je objašnjeno koliko je loša ideja izravno priključivati skupe funkcijescroll
događaju.
Otpuštanje je jedan od načina za rješavanje ovog problema ograničavanjem vremena koje treba proći dok se funkcija ponovno ne pozove. Ispravna provedba debounkinga stoga bi grupirala nekoliko poziva funkcije u jedan i izvršila ga samo jednom nakon proteka određenog vremena. Evo implementacije u obični JavaScript koja koristi teme poput opsega, zatvaranja, ovog i vremenskih događaja:
// debounce function that will wrap our event function debounce(fn, delay) { // maintain a timer let timer = null; // closure function that has access to timer return function() { // get the scope and parameters of the function // via 'this' and 'arguments' let context = this; let args = arguments; // if event is called, clear the timer and start over clearTimeout(timer); timer = setTimeout(function() { fn.apply(context, args); }, delay); } }
Ova će se funkcija - kada se omota oko događaja - izvršiti tek nakon što protekne određeno vrijeme.
You would use this function like so:
// function to be called when user scrolls function foo() { console.log('You are scrolling!'); } // wrap our function in a debounce to fire once 2 seconds have gone by let elem = document.getElementById('container'); elem.addEventListener('scroll', debounce(foo, 2000));
Throttling is another technique that’s is similar to debouncing, except that instead of waiting for some time to pass by before calling a function, throttling just spreads the function calls across a longer time interval. So if an event occurs 10 times within 100 milliseconds, throttling could spread out each of the function calls to be executed once every 2 seconds instead of all firing within 100 milliseconds.
For more information on debouncing and throttling, the following articles and tutorials may be helpful:
- Throttling and Debouncing in JavaScript
- The Difference Between Throttling and Debouncing
- Examples of Throttling and Debouncing
- Remy Sharp’s blog post on Throttling function calls
If you enjoyed reading this article, then you may like reading the JavaScript tutorials and solving some of the JavaScript coding challenges that I host on Coderbyte. I’d love to hear what you think!