Anna Danilec, How to pass JavaScript interview

Ostatnio na Facebooku zauważyłem reklamę darmowego ebooka od Duomly, How to pass JavaScript interview. Postanowiłem się przyjrzeć nieco bliżej tej pozycji.

Tak, pozycja ta nie do końca zgodna jest z ogólnie przyjętymi zasadami WebKrytyka. Postanowiłem je jednak nieco nagiąć z dwóch powodów. Po pierwsze, bardzo dużo osób początkujących w Polsce tak czy inaczej używa materiałów po angielsku i prędzej czy później trafi na tę reklamę. Po drugie, Czechy to jak rzut kamieniem stąd!

  • Zastanawia mnie, czemu zdecydowano się na zamieszczenie wszelkiego kodu jako obrazków. To zdecydowanie obniża dostępność takiego PDF-a, a dodatkowo – utrudnia kopiowanie i sprawdzanie na żywo działania poszczególnych rozwiązań.

  • Nie zgodziłbym się, że w przypadku domknięcia (closure) ważne jest to, że wewnętrzna funkcja nie ma dostępu do obiektu arguments funkcji zewnętrznej. Nie wynika to z samej natury domknięcia, ale tego, że w wewnętrznej funkcji ten obiekt jest przysłonięty przez jej własne argumenty. Można to łatwo udowodnić, używając do stworzenia domknięcia funkcji strzałkowej:

    function outer( a, b ) {
    	const inner = () => console.log( arguments );
    
    	inner();
    }
    
    outer( 1, 2 );

    W tym kodzie funkcja strzałkowa może bez problemu odwołać się do arguments funkcji outer.

    Nie zgodzę się też z tym, że domknięć dobrze jest używać do tworzenia przestrzeni nazw czy ograniczania dostępu do zmiennych. Obecnie obydwie te funkcje lepiej pełnią moduły. Natomiast domknięcia przydają się o wiele bardziej do tworzenia funkcji zwracających inne funkcje.

  • W przypadku opisywania hoistingu oraz różnic pomiędzy sposobami definiowania zmiennych warto poruszyć to, w jaki sposób hoisting działa z let i const, czyli TDZ. Warto też wspomnieć, że hoisting dotyczy także deklaracji funkcji.

  • Funkcje anonimowe i samowywołujące się funkcje to nie jest to samo i zlepianie tych dwóch konceptów jest zbyt dużym uproszczeniem. Funkcje anonimowe najczęściej można spotkać przy przekazywaniu ich jako callbacki do różnych metod, takich jak addEventListener, [].forEach, setTimeout itd.

  • The prototype is an instance of an object from which child object inherits.

    [Prototyp to instancja obiektu, po którym obiekt-dziecko dziedziczy.]

    Technicznie jest to prawda, ale mam wrażenie, że niepotrzebnie to zaciemnia cały obraz. Tym bardziej w dobie ES6+, posiadającego składnię klas. O wiele ważniejsze byłoby stwierdzenie, że prototyp nowego obiektu jest ustalany na podstawie własności prototype jego konstruktora.

  • Podana definicja programowania funkcyjnego jest moim zdaniem mocno zawężona. Brakuje wspomnienia o funkcjach jako obywatelach pierwszej kategorii (functions as first-class citizens), a więc – funkcjach traktowanych jako wartość, dzięki czemu można je m.in. przekazać do innych funkcji.

  • Nie bardzo wiem, czemu do poprawnego utworzenia obiektu miałbym posłużyć się wzorcem Prototyp. Jest on raczej przeznaczony do tworzenia nowych obiektów poprzez kopiowanie obiektu-matrycy. W przypadku JS-a jest to całkowicie niepotrzebne i z powodzeniem można tworzyć nowe obiekty wykorzystując operator new. Być może to pomyłka spowodowana zbieżnością nazw wzorca i mechanizmu dziedziczenia w JS?

  • W przypadku this jego wartość w globalnym zakresie zależy dodatkowo od tego, czy kod jest uruchamiany w strict mode, czy nie. W tym pierwszym wypadku this jest undefined, w tym drugim – window:

    function strict() {
    	'use strict';
    
    	console.log( this );
    }
    
    function sloppy() {
    	console.log( this );
    }
    
    strict(); // undefined
    sloppy(); // window
  • Comparing values in Javascript can be done with type correction or without it.

    [Porównywanie wartości w JavaScripcie może być wykonane z poprawianiem typu lub bez niego.]

    Raczej chodzi o type coercion, nie correction. To nie jest bowiem „poprawianie” typu na „właściwy”. Takiego mechanizmu w JS nie ma, bo to język dynamicznie typowany i „właściwego” typu nie ma. Z kolei jest mechanizm koercji typów, czyli zamiany jednych typów na drugie, który jest dokładnie opisany w specyfikacji.

  • Informacja o zasięgach jest nieprawdziwa. W JS są tak naprawdę trzy zasięgi: globalny, funkcyjny (zwany też czasami lokalnym, chociaż uważam, że obecnie ta nazwa jest dość myląca) oraz blokowy. Ten ostatni został wprowadzony dla let i const. Tym sposobem zasięg nie jest już powiązany tylko z funkcjami, ale także z blokami.

  • Wyjaśnienie bind jest niepotrzebnie zawiłe. Wystarczyłoby napisać, że tworzy dokładną kopię danej funkcji, ale z this ustawionym na wybraną przez nas wartość.

  • Strict mode jest elementem ES5, nie ES6. Tak samo metody tablicowe forEach, map i filter.

    Dodatkowo opis strict mode jest błędny. Zarówno zła składnia, nieistniejące zmienne, jak i obiekty tak samo rzucają błędem poza trybem ścisłym. To są tak podstawowe elementy każdego języka, że JS nie byłby używalny, gdyby nie sprawdzał składni programów przed ich wykonaniem czy nie reagował na używanie niesitniejącej zmiennej. Natomiast warto wspomnieć, że w strict mode nie działają niektóre konstrukcje języka, takie jak with czy arguments.callee, a niektóre dotąd ciche błędy zamieniono na „głośne”, np. nieprawidłowe użycie operatora delete:

    function sloppyDel() {
    	var a = {};
    
    	delete a;
    }
    
    function strictDel() {
    	'use strict';
    
    	var a = {};
    
    	delete a;
    }
    
    sloppyDel(); // *cykanie świerszcza*
    strictDel(); // SyntaxError

    Dodatkowo tryb ścisły można aktywować także na poziomie poszczególnych funkcji (co zrobiłem powyżej), nie musi być to na poziomie całego skryptu. Warto też wspomnieć, że moduły ES mają wymuszony tryb ścisły w swoim wnętrzu.

  • Podana implementacja isArray może dawać złe wyniki w kodzie napisanym w ES6+:

    const fakeArray = {
    	get [ Symbol.toStringTag ]() {
    		return 'Array';
    	}
    };
    
    console.log( Array.isArray( fakeArray ) ); // false
    console.log( isArray( fakeArray ) ); // true
    
    function isArray( value ) {
    	return Object.prototype.toString.call( value ) === '[object Array]';
    }

Niestety, na wiele pytań odpowiedzi są niewyczerpujące, pojawiło się też trochę dość poważnych błędów merytorycznych. A szkoda.

7 komentarzy do “Anna Danilec, How to pass JavaScript interview”

  1. a można wiedzieć co autor tej strony poleca do nauki html, css i javascript? (nie musi być po polsku)
    jestem nowicjuszem i obecnie przerabiam A SMARTER WAY TO LEARN HTML & CSS by Mark Myers, a także Javascript i Python z tej samej serii, podoba mi się forma – krótki rozdział po czym praktyczne ćwiczenie, aby zapamiętać i zastosować w praktyce, jednak brakowało mi „Big Picture”, do czego tak właściwie zmierzam … (wizja i kierunek), szukałem czegoś i trafiłem tutaj za sprawą recenzji – Zawód front-end developer – Maciej Rościszewski, ale jak przeczytałem opinię, że jest to wiedza z 2010 roku, która jest już nieaktualna i się jej nie stosuje,
    to pojawił się we mnie niepokój związany z tym, że być może teraz też uczę się czegoś zupełnie niepotrzebnego – a tego wolałbym uniknąć

    1. Jeśli chodzi o JS, to bardzo dobrym źródłem jest https://javascript.info/

      Jeśli chodzi o HTML, dobrym wstępem jest np. https://the-awwwesomes.gitbooks.io/html-css-step-by-step/pl/

      Jeśli chodzi o tworzenie layoutów w CSS, to dobrym (acz drogim zasobem) jest https://every-layout.dev/

      Co do książki, którą obecnie używasz: sądząc po tym, jak wygląda przykładowy rozdział na Amazonie, sam sposób uczenia jest jak najbardziej efektywny, ale wydaje mi się, że są tam przez to dość spore luki teoretyczne (np. brakuje DOCTYPE).

      1. Jestem kolejnym początkującym. Uczyłem się z javascript.info, ale poprzestałem ze względu na ilość niepotrzebnych mi w danym momencie informacji. Ostatecznie wziąłem kurs z Udemy (jako formę wideo) i dokumentację Mozilli. Kolega (nigdy nie pracował) polecił mi ten sposób uczenia się (JIT). Według niego zaletą takiego podejścia jest natychmiastowy efekt (co zresztą sam zauważyłem). Wcześniej czytałem, mało co robiłem. Książkę Eloquent Javascript odpuściłem sobie po 3 stronach.

        Dosłownie przed chwilą wygooglowałem hasło „web components” i natrafiłem na bloga comandeer.pl. Dowiedziałem się, że nie warto z tego korzystać, m. in. przez bezmyślność twórców tego rozwiązania i ogólną bezsensowność idei pakowania logiki w znaczniki HTML. Wybrałem to, bo chciałem samodzielnie stworzyć elegancki routing oraz zastosować wzorzec MVC w mojej pierwszej aplikacji (bez frameworka). Chwilę później doczytałem, że Angular stosuje podobne, nieoptymalne praktyki (np. [ng-click]). Niedawno zacząłem się go uczyć. Powodem była inspiracja wspomnianego wcześniej kolegi. Pisze się prosto, ale za cholerę nie wiem jak to wszystko działa (co jest pod maską). Kolega twierdzi, że wiedzieć tego wcale nie trzeba, że wystarczy zrozumieć koncept.

  2. Nie dokończyłem swojej wypowiedzi. Co powinienem zrobić w tym momencie? Zdaniem innych Angular to ślimaczy, kobylasty framework pełen wad. Z kolei pisanie funkcjonalnej aplikacji od zera w czystym JS sprowadza się do stworzenia czegoś na wzór małego frameworka – niekonicznie w optymalny sposób. Chciałbym, żeby mój wybór technologii był mniej przypadkowy, a moje działanie do czegoś prowadziło. Nie tylko do zapamiętania skrawka informacji z jakiejś książki.

    1. Web Components to technologia niedojrzała. Niemniej nie wymusza wsadzania logiki do HTML-a, można stworzyć komponenty, które będą całkowicie pozbawione logiki.

      Co do Angulara, obecna wersja wygląda zupełnie inaczej od tego, która jest opisana na WebKrytyku. Niemniej wciąż jest to framework klasy enterprise i jest najbardziej rozbudowany i trudny do zrozumienia z tzw. wielkiej trójcy. Wydaje mi się, że na chwilę obecną najłatwiejszy do ogarnięcia jest Vue.js.

      Nie zgodzę się też, że nie trzeba wiedzieć, co dzieje się pod maską. Taka wiedza przydaje się, gdy trzeba optymalizować aplikację lub debugować bardziej złożone problemy.

Skomentuj Maritime Anuluj pisanie odpowiedzi

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *

Witryna wykorzystuje Akismet, aby ograniczyć spam. Dowiedz się więcej jak przetwarzane są dane komentarzy.