Web developer – pytania rekrutacyjne cz. 3

Ten artykuł jest kontynuacją cyklu wpisów związanych z pytaniami rekrutacyjnymi na stanowisko web developera. Jeśli jeszcze nie zapoznałeś/aś się z poprzednimi artykułami z tej serii to gorąco zachęcam Cię do nadrobienia zaległości:

Tak jak w poprzednich artykułach przedstawię 10 pytań wraz z odpowiedziami i omówieniem. Źródłem pytań jest aplikacja fefaq oraz własne doświadczenia. Zaczynajmy więc!

1. Jaki będzie wynik poniższego kodu? Dlaczego otrzymamy taki wynik?

function foo() {
  for(var i=0; i<10; i++) {
    setTimeout(function() {
      console.log(i);
    }, 300);
  }
}
foo();

Teraz proszę przerwij na chwilę czytanie tego artykułu i zastanów się nad odpowiedzią. Pomyśl jakiej udzieliłbyś odpowiedzi, a następnie zobacz jakiej udzieliłem ja.

Na pewno znajdą się osoby, które podały odpowiedź: liczby od 0 do 9. Osoby te miałyby rację w momencie, gdybyśmy słowo var zastąpili słowem let. Powstałaby wtedy zmienna o zasięgu blokowym (block scope), w konsekwencji czego rezultat naszego kodu byłby zgoła inny. Var nie jest w stanie wytworzyć takiego zasięgu. Odpowiedzią na to pytanie będzie wyświetlenie w konsoli 10 razy liczby 10. Dlaczego otrzymamy taki wynik? Pętla zdąży wykonać się zadaną ilość razy, a iterator osiągnie wartość maksymalną (czyli 10) zanim wykona się funkcja przekazana do setTimeout().

Pytania rekrutacyjne - Czerwone ferrari

2. Jaka jest różnica między klasą a obiektem?

Klasę możemy zdefiniować jako swojego rodzaju schemat, natomiast obiekt jest to konkretny powołany do życia byt na podstawie stworzonego wcześniej schematu (klasy). Dla przykładu tworząc klasę Car mającą za zadanie przedstawić samochód deklarujemy w niej cechy takie jak kolor, marka, rodzaj spalanego paliwa itd., a także metody tj. jedź, hamuj, skręcaj. Tworząc obiekt na podstawie definiujemy już konkretne właściwości jakie ma mieć ten samochód, czyli w naszym przypadku może być to na przykład czerwone Ferrari z silnikiem benzynowym.

3. Jakie znasz struktury danych?

W przypadku takiego pytania myślę, że najprościej jest je po prostu wymienić:

  • Stos
  • Kolejka
  • Lista
  • Drzewo binarne
  • Graf

Samych struktura danych jest oczywiście więcej. Przedstawiłem jedynie najpopularniejsze i najbardziej podstawowe, choć i te można podzielić, jak chociażby listy na jedno- i dwukierunkowe. Pełną listę znajdziesz w źródłach i materiałach dodatkowych na końcu tego wpisu.

4. Czym jest barrel w ES6 i do czego służy?

Prawdę mówiąc ze słowem barrel zetknąłem się po raz pierwszy przy zobaczeniu tego pytania. Inną nazwą tego usprawnienia jest destructuring lub też po polsku destrukturyzacja. Za pomocą destrukturyzacji w bardzo prosty sposób możemy przypisywać właściwości obiektów do konkretnych zmiennych. Destrukturyzacja pomocna okazuje się też w przypadku importowania cech i metod z zewnętrznych plików.

const person = {
  name: 'John',
  surname: 'Doe'
};

const { surname } = person;
console.log(surname);

Jak widać destrukturyzacja pozwala nam na uszczuplenie naszego kodu. Być może nie jest to tak widoczne w tym przykładzie, jednak mając duże obiekty i wykorzystując ich właściwości sprawiamy, że nasz kod jest mniejszy objętościowo i staje się znacznie bardziej czytelny. Pomijamy wielokrotne odwoływanie się do obiektu – w naszym przypadku person. Oprócz tego oszczędzamy sobie pisania.

5. Jakie kodowanie znaków (charset) jest rekomendowane dla j. polskiego?

Rekomendowanym charsetem dla języka polskiego jest UTF-8. Charset ustawiamy za pomocą znacznika meta w sekcji head naszej strony.

<meta charset="UTF-8">

6. Wytłumacz na czym polega hoisting.

Hoisting występuje w przypadku zadeklarowania zmiennej lub funkcji słowem kluczowym var. Hoisting powoduje, że deklaracje zmiennych są wywoływane w pierwszej kolejności przed wykonaniem reszty kodu. Co trzeba zaznaczyć hoisting jedynie deklaruje zmienne a nie przypisuje im wartości, Myślę, że dobrze zobrazuje to przykład:

console.log(a);
var a = 4;
console.log(a);

Po wykonaniu tego kodu widzimy, że zmienna a została zdefiniowana, ale nie przypisano jej wartości. Zamień teraz w pierwszym console logu zmienną a na dowolną inną i zobacz jaki komunikat otrzymasz w konsoli. Zjawisku hoistingu nie ulegają zmienne zadeklarowane słowami let oraz const.

console.log(a);
let a = 4;
console.log(a);

Tutaj otrzymamy błąd o treści: ReferenceError: a is not defined.

Pytania rekrutacyjne - fonty

7. Dodawanie czcionek poprzez link vs poprzez import. Co wybierzesz?

Wybiorę dodawanie czcionek poprzez znacznik link. Wynika to przede wszystkim z wydajności tego rozwiązania. Czcionki importowane przez @import są ładowane sekwencyjnie, natomiast czcionki ładowane przy pomocy link są ładowane równolegle. Link do testów badający wydajność importowania czcionek znajdziesz w źródłach na końcu tego wpisu.

8. Czym jest plik reset.css i czym różni się od normalize.css

Każda z przeglądarek domyślnie posiada zdefiniowane podstawowe style. Co więcej, dla każdej z nich owe style mogą się różnić (i zwykle się różnią). Zostawienie ich w domyślnej postaci spowodowałoby, że nasza strona na różnych przeglądarkach wyglądałaby inaczej, a tego przecież nie chcemy. Do poradzenia sobie z tym możemy wykorzystać 2 pliki: reset.css oraz normalize.css.

Pierwszy z nich powoduje zresetowanie styli przeglądarki. Dzięki temu na każdej przeglądarce nasza strona będzie wyglądać identycznie. Z kolei normalize.css nie resetuje styli, a nadaje własne nadpisując przy tym domyślne style przeglądarki.

9. Jaka jest różnica między var, let i const? Który jest preferowany?

Przede wszystkim to wcześniej wspomniany już hoisting. Oprócz tego zmienne typu let oraz const mogą tworzyć zasięg blokowy. Dodatkowo jak nazwa wskazuje const jest “wartością stałą”, czyli nie możemy mu przypisać ponownie wartości. Jak zwykle najlepszy będzie przykład:

if(true) {
  var a = 4;
  console.log(a);
}
console.log(a);

if(true) {
  let b = 1;
  console.log(b);
}
console.log(b);

Najbardziej preferowany w użyciu jest const, w drugiej kolejności let, zaś w przypadkach, gdy nie możemy ich użyć pozostaje nam użycie var.

Pytania rekrutacyjne - stos

10. Zaimplementuj stos (Stack) w JS

Stos, który stworzę będzie miał 2 funkcje: wrzucania elementu na stos oraz zdejmowania elementu ze stosu. Stos jest strukturą LIFO, czyli Last In First Out. Oznacza to, że ostatni umieszczony na stosie element jest z niego zdejmowany w pierwszej kolejności. Przejdźmy zatem do implementacji:

const stack = {
  items: [],
  push: function(arg) {
    return this.items.unshift(arg);
  },
  pop: function() {
     if(this.items.length) return this.items.shift();
  }
}

stack.push(9);
stack.push(4);
stack.push(1);
stack.push(5);
stack.push(5);
stack.push(16);
stack.push(2);
stack.pop();
stack.pop();
console.log(stack.items); //expected output: [5, 5, 1, 4, 9]

Mam nadzieję, że ten artykuł okazał się dla Ciebie pomocny. Jeśli coś wydaje Ci się niejasne, lub też zauważyłeś błąd to koniecznie napisz mi o tym w komentarzu. Zachęcam też do pozostawienia oceny pod artykułem! Napisz mi też jakie pytania rekrutacyjne usłyszałeś na swoich rozmowach oraz jakich odpowiedzi na nie udzieliłeś. Jak zwykle zachęcam do zapoznania się ze źródłami i materiałami dodatkowymi.

Źródła i materiały dodatkowe