Quiz JavaScript

Przygotowałem mały quiz JavaScript. Zachęcam do zabawy i podawania wyjaśnień w komentarzach. Jednocześnie uczulam na spoilery. Być może wkrótce pojawią się inne quizy tego typu. Odpowiedź ERROR oznacza błąd – jakiegokolwiek typu, nie wnikamy tutaj w szczegóły. Kod powinien być zgodny z ECMA w trzeciej edycji plus mały dodatek w postaci funkcji map z kolejnych edycji.

  1. var fn = function x () { return fn; };
    x;

  2. ["1", "2", "3"].map(parseInt);

  3. parseInt("08");

  4. 10.2 | 0;

  5. typeof Number("2");

  6. var obj = {
    	a : this.obj,
    	obj : "foo"
    };
    typeof obj.a; 

  7. var arr = [1, 2, 3];
    arr.splice(1, 0, 1);
    arr;

  8. var x = [1, 2, 3].splice(1, 1);
    x;

  9. 0..toString.call(2, 2);

  10. [1.,.5][0.1 & 0]

  11. var x = (1, 2, (x = 3), 4);
    x;

  12. var var = "100";
    var;

  13. [10, 100, 1][~"2" + + "3"];

  14. var fn = function gn () {
    	var hn = function gn () {
    		fn();
    		return 100;
    	};
    	return hn;
    };
    fn()();

  15. "" + [1] + {};
    	        

  16. var x = ({ "with" : 1} + 1);
    x;

  17. var x = [[] | 0];
    x;

  18. Infinity > NaN;

  19. undefined < 1;

  20. /[a-z]/g == /[a-z]/g;

Komentarze

1

Kiepski jestem w tych quizach. Niby wiem te rzeczy, ale zawsze daję się nabierać :D 16/20.

I dwóch nie rozumiem:
2. dlaczegóż?
13. co jest wstawiane pomiędzy dwa plusy? 0?

2

Nie widzę korzyści z opanowywania języka i jego silników do tego stopnia, żeby móc takie testy robić na 100%. Ale na pewno fajnie by było wiedzieć ;)

12/20

3

A poległem jeszcze na porównaniu regexpów i 19. Czyli w sumie… Jednak niewiedza.

Swoją drogą jak pierwszy raz testowałem Number(undefined) to dostałem 2 :D Później sobie przypomniałem, że chwilę temu, wczytując się w specyfikację, głowiłem się czemu undefined nie jest zarezerwowanym słowem i dlaczego można zrobić undefined = 2;

4

W 18 masz literówkę, albo brakuje poprawnej odpowiedzi ERROR;)

Dobry test, jest z czym posiedzieć przy dokumentacji.

Pozdrawiam

5

Racja, fixed. Dzięki!

6

Bardzo ciekawy test, aczkolwiek nie zajmowałem się na tyle JavaScriptem, żeby móc uzyskać tutaj jakiś szczególnie wysoki wynik. W PHP i owszem, mógłbym wystartować, ale tutaj po prostu wolę jednak stanąć z boku. ;]

7

Osoba która można powiedzieć, że nie ma pojęcia o JavaScripcie (a co dopiero mówić o takich szczegółach jak w tym quizie), rozwiązując quiz na szybko zdobywa 7/20 punktów.

35% to całkiem niezły wynik – maturę z javaScriptu bym zdał :D.

PS. Po czym mam rozpoznać na które punkty odpowiedziałem poprawnie?

Saskatchewan
8

@Saskatchewan nie przygotowalem oznaczen, ktore dobrze, ktore zle, wiec pozostaje Ci klikanie i sprawdzanie. Caly czas licze tez, ze ktos napisze tutaj potem rozwiazania z objasnieniem.

9

Ok, dodałem oznaczenie kolorystyczne ;-)

10

17/20, ale pewien nie byłem w kilku wypadkach. swoją drogą, brr! zamordowałbym tego, kto by takie rzeczy w kodzie tworzył.

11

A mnie ciekawi, czemu zadanie 16 wywala się w Operze :>

KORraN
12

Poprawione, by wszędzie działało tak samo ;-)

13

to ja się pokuszę o skrótowe wyjaśnienie, chociaż w paru miejscach nie jestem pewien, więc proszę o poprawki jakby co ;)

1. to tzw. named function expression, x dostępne powinno być w scope funkcji (bezposrednio jako funkcja, oraz jako string arguments.callee.name), ale nie poza nim. powinno, ponieważ w IE6 wycieka do global scope’a.

2. map przekazuje do swojego callbacka 3 parametry: element obecnie podlegający obróbce, index tego elementu oraz scope. w tym wypadku do parseInt jako radix przekazany zostaje index elementu.

3. brak przekazanego radix’a dla parseInt = parseInt próbuje określić go sam = fail. to błąd, w strict mode chyba w ogóle by nie poszło.

4. bitwise OR, zwraca 1 dla jeśli którykolwiek z porównywanych bitów == 1. jest to jeden ze sposobów na Math.floor, daje błędne(niechciane) wyniki przy ujemnych.

5. Number(„string”) to jeden ze sposobów na castowanie do number, nie polecany.

6. obiekt w object literal zostaje utworzony od razu ze wszystkimi swoimi własnościami, od góry do dołu, zatem „a” wskazuje na nieistniejące jeszcze „this.obj”. gdyby zamienić własności miejscami, wynikiem byłby „object”.

7. takie wywołanie Array.splice oznacza „zaczynając od pierwszego elementu(indexu) tablicy, usuń 0 elementów i dodaj element 1”

8. „zaczynając od pierwszego elementu(indexu), usuń jeden element”. splice zwraca usuwane elementy w postaci nowej tablicy.

9. 0. === 0, tak jak .5 === 0.5. kropka jest po to żeby umożliwić wywołanie metody bezpośrednio na prymitywie number (jak to się dokładniej dzieje, nie wiem. oszukanie interpretera?) równie dobrze mogłoby być (0).toString. poza tym, 0 jest zupełnie bez znaczenia, bo pierwszym argumentem jaki przyjmuje call jest kontekst ‚this’, w tym wypadku 2. kolejne argumenty call zostają przekazane jako argumenty do funkcji na rzecz której został wykonany, zatem po prostu zamieniamy 2 na system dwójkowy.

10. kropki dla zmyłki (patrz wyżej), bitwise AND zwraca 1 dla każdego jednakowego bitu w obu cyfrach, i… tutaj kończy się moja wiedza, nie wiem co się dzieje przy konwersji ułamków do systemu binarnego ;)

11. wyrażenia w nawiasie zostają wykonane w kolejności od lewej do prawej, zwrócony zostaje wynik ostatniego wyrażenia.

12. var jest keywordem.

13. ~”2″ to bitwise NOT, zamienia 0 na 1 a 1 na 0. dla liczb całkowitych, wynikiem takiej zamiany jest liczba o przeciwnym znaku – 1. drugi plus rzutuje „3” na Number (+”3″ === parseInt(„3”,10)), zatem mamy [10, 100, 1][-3 + 3]

14. wywołany zostaje efekt działania funkcji fn, czyli funkcja gn, która wywołuje funkcję fn jeszcze raz, a następnie kończy swoje działanie zwracając 100. najwyraźniej kończąc działanie kończy jednocześnie działanie funkcji, którą wywołała. closure? ktoś by tu mógł napisać coś więcej, bo nie do końca wiem czemu nie wchodzimy w infinite loop.

15. zaczynamy od prawej. dodawanie do siebie obiektów różnego typu powoduje: 1. rzutowanie ich do stringa (wywołanie ich metody toString), 2. dodanie stringów. zatem mamy ‚1’ + ‚[object Object]’, czyli ‚1[object Object]’. kolejne działanie, czyli dodanie pustego stringa, nie ma już znaczenia.

16. podobnie jak powyżej, dodajemy do siebie dwa różne typy obiektów, co powoduje rzutowanie do stringa.

17. działania arytmetyczne (w tym bitwise) inne niż dodawanie (które są rozumiane jako konkatenacja) rzutują do number. pusta tablica zrzutowana do number to 0, 0 | 0 to nadal 0, zatem otrzymujemy tablicę której jedynym elementem jest 0.

18. NaN nie jest równe, mniejsze ani większe od niczego, nawet od NaN.

19. undefined nie jest mniejsze ani większe od niczego, a równe jest jedynie undefined.

20. RegExp jest funkcją. próba bezpośredniego porównania ze sobą obiektów, tablic czy funkcji daje false.

14

@wildcard:
19. undefined jest równe tylko undefined’owi i null

3. brak przekazanego radix’a dla parseInt = parseInt próbuje określić go sam = fail. to błąd, w strict mode chyba w ogóle by nie poszło.

W parseInt w Ecmascript 5 nadal wartości zaczynające się od 0x wskazują na system 16-tkowy.
Tak na marginesie, zapis liczb ósemkowo został zepchnięty do statusu rozszerzeń w celu zapewnienia kompatybilności z wcześniejszymi wersjami specyfikacji, jednak z wyłączeniem strict mode.

10. kropki dla zmyłki (patrz wyżej), bitwise AND zwraca 1 dla każdego jednakowego bitu w obu cyfrach, i… tutaj kończy się moja wiedza, nie wiem co się dzieje przy konwersji ułamków do systemu binarnego ;)

Wewnętrznie wywoływane jest zawsze ToInt32. To chyba tłumaczy wszystko ;-)

15

14. wywołany zostaje efekt działania funkcji fn, czyli funkcja gn, która wywołuje funkcję fn jeszcze raz, a następnie kończy swoje działanie zwracając 100. najwyraźniej kończąc działanie kończy jednocześnie działanie funkcji, którą wywołała. closure? ktoś by tu mógł napisać coś więcej, bo nie do końca wiem czemu nie wchodzimy w infinite loop.

Zapis jest dość zakręcony, ale jak się powoli przeanalizuje co się tam dzieje, to dojdziesz dlaczego nie ma nieskończonej pętli.
W każdym razie, jeśli wewnątrz funkcji gn zamiast fn() dałbyś fn()() to miałbyś nieskończoną pętlę. Gdy jest samo fn(), to wywołanie zwraca tylko tę wewnętrzną funkcję i nic więcej nie robi, dlatego można spokojnie przejść do return 100. Prościej wyjaśnić nie potrafię.

16

do Rafał Kukawski
Prosciej nie trzeba – jest ok.
Ja sie nacialem :) Bo jak przez zmienna uzyskuje sie dostep do funkcji, ktora po wywolaniu zwraca funkcje, ktora natychmiast wywolujemy to mozna a w niej jest znowu wywolanie tej pierwszej funkcji poprzez wspomniana globalna zmienna to sie mozna w pierwszym momencie zdziwic :)

Oli
17

Hmmm… zaplątałem się w moim poprzednim komentarzu :)

Oli
18

A mnie ciekawi, czemu zadanie 16 wywala się w Operze :>

Dlatego że Opera ma błąd: http://code42.pl/2010/12/22/zarezerwowane-slowa-kluczowe-w-javascript-gramatyka-jezyka/

19

17/20, gratuluje inwencji:)

20

;/ Ale słabo, to jest trzeci poziom wtajemniczenia JS, ja jestem dopiero na 2.

red_sky
21

Bardzo fajny quiz, od jakiegoś czasu szukałem podobnych zadań.
Znalazłem ich trochę w nowej wersji Varjs, za co dziękuję autorowi. Na prawdę cały blog jest to kawał rzetelnej wiedzy.
Ale wracając do testu, mój wynik to 14/20 spędziłem przy nim z przyjemnością trochę czasu, pozostaje kilka pytań do analizy
czekam na kolejne quizy tego typu

tomek
22

@wildcard

Co do 6pkt, wynikiem jest undefined, bo chyba obiekt nie został stworzony przez operator new, zamiana kolejności nic nie daje.

23

@Adam
> var obj = { checkThis: function() { return this } }
> obj.checkThis()
{ checkThis: [Function] }

this w kontekscie obiektu stworzonego przy uzyciu object literal odnosi sie do owego obiektu. masz natomiast racje co do tego, ze zmiana kolejnosci nic nie zmienia :)

Dodaj komentarz

Dozwolone tagi: <blockquote>, <code>, <strong>