Pytania rekrutacyjne cz. 2

Web developer – pytania rekrutacyjne cz.2

Oto już drugi wpis na moim blogu zawierający zestaw pytań rekrutacyjnych na stanowisko Web Developera. Tak samo jak w poprzednim wpisie pytania pochodzą z fefaq.pl – bazy z pytaniami rekrutacyjnymi tworzonej przez społeczność. Jeśli nie zapoznałeś/aś się jeszcze z poprzednim artykułem o tej tematyce to zachęcam do nadrobienia zaległości: Web developer – pytania rekrutacyjne cz. 1. Tak jak w poprzednim wpisie poznasz 10 pytań wraz z odpowiedziami i objaśnieniami.

Wpis ten jest jednym z serii wpisów. Pozostałe artykuły z tej serii znajdziesz tutaj:

A teraz przejdziemy do pytań!

1. Co to są falsy values? Jakie falsy values znasz?

Falsy values są to wartości, które użyte w kontekście flagi zwrócą nam wartość false. Najbardziej trywialnym przykładem na jakim możemy to zobrazować będzie zwykły if(). Przekazując do niego jako parametry będące falsy values warunek nie zostanie spełniony. Wyróżniamy następujące ‘fałszywe wartości’:

  • false,
  • null
  • undefined,
  • 0,
  • NaN,
  • pusty string

2. Jak przejąć kontrolę nad right-click’iem myszki?

Do przejęcia kontroli nad prawym przyciskiem myszy służy event auxclick. Prawy klik myszy obsługujemy jak kadży inny event w JavaScript. Przykład kodu wykorzystującego to zdarzenie:


document.addEventListener('auxclick', function() {
  console.log('Hello!');
});

3. Na czym polega referencja? Jakie typy danych są przekazywane przez referencję w JS?

Referencja jest to swojego rodzaju adres (odniesienie do) wartości w pamięci. W JavaScript typem referencyjnym jest Object (oraz Array, który tak naprawdę też jest typem Object). Przeanalizujmy poniższy przykład:


const hobbit1 = {
  name: "Bilbo",
  surname: "Baggins"
}

const hobbit2 = hobbit1;

hobbit2.name = "Frodo";

console.log(hobbit1);
console.log(hobbit2);

Po uruchomieniu kodu zapewne zauważyłeś że imię Frodo zostało przypisane obu hobbitom. Dlaczego się tak stało? Bo tak naprawdę obie zmienne odwołują się do tego samego hobbita! Tworząc zmienną hobbit2 tak naprawdę nie skopiowaliśmy naszego obiektu tylko referencję do niego. Co więcej, warto zwrócić uwagę jak typy referencyjne mają się do słowa kluczowego const. Zmiana imienia nie powoduje zmiany referencji, czyli nasza zmienna hobbit2 pozostała niezmieniona w konsekwencji czego nie otrzymujemy błędu. Zobacz co się stanie gdy przed instrukcją console.log() dodasz następujący kod:


hobbit2 = {
  name: "Sam",
  surname: "Gamgee"
}

W tym momencie nastąpiła prób zmiany referencji i zastąpienia jej referencją do nowego obiektu co spowodowało błąd (próba zmiany wartości zmiennej zadeklarowanej słowem kluczowym const).

Kolejnym ciekawym zagadnieniem dotyczącym typów referencyjnych jest porównywanie ich ze sobą. Rzućmy okiem na przykład:


const hobbit1 = {
  name: "Bilbo",
  surname: "Baggins"
}

const hobbit2 = {
  name: "Bilbo",
  surname: "Baggins"
}

const hobbit3 = hobbit2;

console.log(hobbit1 == hobbit2);
console.log(hobbit2 == hobbit3);

Jak widzisz porównując zmienne będące referencjami nie porównujemy tak naprawdę obiektów a ich referncje. Mimo tego, że są to identyczne obiekty, to w pamięci komputera mają one inne adresy w pamięci przez co ich referencje są zupełnie różne w konsekwencji czego pierwszy console.log() wskaże false. W drugim przypadku skopiowaliśmy referencję i odwołujemy się do tego samego hobbita, czyli wynikiem będzie true.

4. Jak zastosować dziedziczenie w SCSS?

Do zastosowania dziedziczenia w SCSS możemy podejść dwojako. Pierwszy ze sposobów na dziedziczenie kodu to skorzystanie z instrukcji @extend. Drugi sposób to instrukcja @mixin. Rezultat jaki zobaczymy wizualnie w przeglądarce będzie identyczny, niezależnie od zastosowanego rozwiązania. Różnice między nimi bardzo dobrze opisuje wpis na StackOverflow, do którego link znajdziesz na końcu tego wpisu. Jeśli interesują cię detale i szczegółowe zastosowanie obu rozwiązań to zdecydowanie warto się zapoznać z tym materiałem. Tymczasem zobaczmy przykład:


@mixin btn {
  padding: 15px 20px;
  border: none;
  outline: none;
  background-color: rgb(66, 103, 178);
  color: #fff;
  font-weight: bold;
  font-size: 20px;
}

.btn {
  padding: 15px 20px;
  border: none;
  outline: none;
  background-color: rgb(66, 103, 178);
  color: #fff;
  font-weight: bold;
  font-size: 20px;
}

.btn-default {
  @extend .btn;
}

.btn-danger {
  @extend .btn;
  background-color: #f00;
}

.btn-success {
  @include btn;
  background-color: #0f0;
}

Będąc przy temacie @extend oraz @mixin warto też poruszyć temat funkcji w SCSS. Do stworzenia funkcji służy instrukcja @function. Funkcje mogą być niezwykle przydatne do tworzenia chociażby dynamicznych wartości czy obliczeń. W poniższym przykładzie stworzyłem funkcję ustawiającą szerokość elementów z klasą .btn na wielokrotności 150px:


@function setWidth($number){
  @return 150px * $number
}
.btn-success {
  width: setWidth(2);
}
.btn-danger {
  width: setWidth(1);
}

5. Dlaczego zazwyczaj skrypty podłączamy przed zamknięciem tagu body?

Domyślnie podczas ładowania skryptu za pomocą tagu <script> parsowanie HTML’a zostaje wstrzymane do czasu zakończenia działania skryptu. Takie działanie powoduje kilka komplikacji.

Przede wszystkim opóźniamy ładowanie naszej strony. Ładując masywny skrypt możemy spowodować, że odbiorca później zobaczy zawartość naszej witryny.

Drugą komplikacją jest odwoływanie się do elementów drzewa DOM. Zgodnie z tym co opisałem wcześniej parsowanie HTML’a zostaje wstrzymane do czasu zakończenia wykonywania skryptu. Oznacza to, że dodając znaczniki <script> do heada powodujemy, że body się nie zdąży załadować, przez co próba jakichkolwiek operacji na elementach DOM będzie skutkowała błędami, (elementy DOM’u nie zostały jeszcze stworzone). Oczywiście można sobie z tym poradzić i skorzystać chociażby z eventu DOMContentLoaded, jednakże uważam, że przeniesienie skryptu przed zamknięcie tagu body jest szybsze i prostsze.

6. Wyjaśnij różnicę pomiędzy <script async> i <script defer>

Jest to pytanie ściśle powiązane z poprzednim. Aby uporać się z problemami opisanymi w poprzednim pytaniu możemy skorzystać właśnie z async lub defer.

Async powoduje, że skrypty nie wstrzymują parsowania HTML’a podczas ładowania. Wstrzymanie następuje jednak w momencie wykonywania skryptów.

Defer również nie powoduje wstrzymania parsowania HTML’a. Różny jest jednak moment wykonania skryptów. W tym przypadku kod wykona się dopiero po zakończeniu parsowania HTML’a.

7. Co to jest chmod?

Może nie jest to zagadnienie ściśle powiązane z kodowaniem, natomiast jest to pytanie jak najbardziej przydatne – wykorzsytamy je chociażby przy uploadzie plików na serwer. Polecenie chmod znajdziemy w systemach z rodziny Linuxa oraz na systemach na komputerach firmy Apple. Polecenie to definiuje prawa dostępowe do danego pliku bądź katalogu.

Składnia polecenia chmod wygląda następująco: chmod [liczba][liczba][liczba] nazwa_katalogu. Liczby te nie są przypadkowe:

  • 4 – prawa do odczytu
  • 2 – prawa do zapisu
  • 1 – prawo do wykonania
  • 0 – brak uprawnień

Liczby te możemy ze sobą dodawać, tak aby przyznać więcej niż jedno uprawnienie. Każda z liczb w poleceniu odpowiada za inną segment użytkowników. Pierwsza z nich to uprawnienia właściciela, druga grupy, zaś ostatnia dotyczy pozostałych użytkowników. Możemy też skorzystać z flagi -R, aby nadać uprawnienia rekursywnie czyli wraz z plikami i podkatalogami w danym katalogu.

Rozważmy przykład: chcemy nadać właścicielowi katalogu “www” wszystkie możliwe uprawnienia, grupie prawa do odczytu, zaś pozostałym użytkownikom nie chcemy nadać żadnych praw. Pliki i podkatalogi również mają mieć identyczne uprawnienia. Polecenie będzie wyglądało następująco: chmod -R 740 www.

8. Czym jest REST API?

Na ten temat powstał na moim blogu artykuł Wstęp do REST API cieszący się ogromną popularnością. Serdecznie zachęcam do zapoznania się!

9. Jakie polecenie pokazuje ostatnie commity?

Czas na pytanie z GIT’a! Poleceniem pokazującym ostatnie commity jest polecenie git log. Do polecenia git log możemy zastosować kilka ciekawych flag:

  • –oneline – dzięki tej fladze każdy commit zostanie wyświetlony w jednej linii,
  • –author=<pattern> – pozwala na wyświetlenie commitów konkretnego autora,
  • –graph – wyświetla nasze commity w eleganckim drzewku,
  • –skip=<number> – pozwala pominąć n ostatnich commitów.

Samych flag jest oczywiście znacznie więcej. Całą listę (naprawdę obszerną) znajdziesz na końcu wpisu w źródłach.

10. W jaki sposób się rozwijasz w programowaniu?

Nie jest to co prawda pytanie stricte techniczne, niemniej jednak istnieje bardzo duża szansa, że je usłyszysz. Samych sposobów na rozwijanie swoich umiejętności programistycznych jest całkiem sporo, i dla przedstawię tu kilka z nich:

  • Czytanie blogów programistycznych,
  • Pomaganie na forach i StackOverflow – poprzez pomaganie człowiek również się uczy,
  • bierny i czynny w konferencjach, meetupach, warsztatach i hackatonach,
  • czytanie książek,
  • oglądanie poradników,
  • przechodzenie kursów,
  • szkoły programowania, bootcampy i uczelnie wyższe,
  • aktywny udział w grupach na Facebooku, Slackach i Discordach programistycznych,
  • udział w konkursach,
  • a przede wszsystkim praktyczne programowanie i realizacja projektów!

Z zagadnieniami rozwoju w programowaniu stykałem się na tym blogu już niejednokrotnie. Po więcej informacji zapraszam do poniższych artykułów:

11. BONUS – Jaka jest różnica między Java a JavaScript?

Mniej więcej taka jak pomiędzy hamhamster. (Oczywiście jest to żart i nie należy traktować tego pytania poważnie).

Źródła i materiały dodatkowe: