JavaScript u 10 dana (1995)

Jezik koji je danas svugdje nastao je za deset dana, iz dosade, žurbe i marketinškog trika s imenom Jave — i nikad ga nije stigao popraviti.

poglavlje 6/2720 min čitanja1991 – 2000
ti@kronika:~$ ./sviraj K4_6_javascript.mp3

# da, poglavlje ima pjesmu. ne, nitko ne zna zašto.

Svibanj 1995. U uredima Netscapea u Mountain Viewu nitko ne spava dovoljno — rat s Microsoftom vodi se u tjednima, ne u kvartalima, i tempo je takav da ljudi odu na roditeljski sastanak, a vrate se s tri nova zahtjeva na stolu. Browser wars, sjećaš se, ono poglavlje. Ova priča događa se unutar njega, u jednom malom, naizgled sporednom hodniku te zgrade.

U isto vrijeme, u drugoj zgradi i drugoj priči, Sun Microsystems upravo izbacuje programski jezik Java, i cijela industrija nakratko poludi. Ne zbog onoga što Java stvarno radi, nego zbog onoga što obećava: napiši kod jednom, a radit će na bilo kojem računalu, bilo kojem sustavu, bez prepravki. Marketinški san, mantra koju izgovaraš na sastanku da zvučiš kao da znaš kamo ide budućnost. Netscape to želi. Netscape to MORA imati u svom browseru, jer ako Java uđe u Netscape a ne u Internet Explorer, to je poen — a poeni su trenutno jedino što se broji.

Ali Java je teška. Java se kompilira — što znači da prije nego što je uopće pokreneš, moraš je prevesti u jezik razumljiv računalu, poseban korak, poseban program, malo čekanja — dok skriptni jezik samo pročitaš i odmah izvršiš, bez te stanke. Java traži disciplinu, Java nije za nekog jadnika koji samo želi da mu formular na stranici kaže korisniku 'ej, zaboravio si upisati e-mail' prije nego što se ta forma pošalje preko cijelog interneta do servera koji će mu, deset sekundi kasnije, reći potpuno istu stvar. Treba nešto sitno. Nešto ljepljivo, brzo, nešto što se ubaci u HTML kao naljepnica i radi u tom istom trenu, u browseru, bez putovanja do servera i natrag. Igračka. Ozbiljno — tako su je i zamišljali. Igračka za formice, za dizajnere koji ne znaju pointer ni što je to, za onaj jedan posto interaktivnosti koji web stranica iz 1995. uopće smije sanjati imati.

Taj zadatak, u toj žurbi, pada na stol jednom čovjeku koji je u firmi tek nekoliko tjedana. Ne timu. Čovjeku. I dobiva rok koji zvuči kao urbana legenda čak i ljudima koji su ga sami izmislili — deset dana. Ne deset tjedana. Deset dana da se iz ničega napravi programski jezik koji će, iako to tada nitko, baš nitko u toj zgradi ne zna niti sanja, za dvadesetak godina pokretati svaku stranicu koju ćeš ikad otvoriti.

Svibanj 1995. Taj zadatak dobiva novi zaposlenik, po imenu Brendan Eich, koji je u firmi tek nekoliko tjedana.

Rok: deset dana.

Netscape 2.0 mora izaći, a marketing je već obećao da će preglednik imati i „ozbiljan” jezik, Javu, koju ugrađuju kao pokretač apleta — sitnih programčića koji se učitaju unutar web-stranice i tamo odrade svoj posao, poput minijaturne aplikacije zalijepljene na stranicu — i taj drugi, mali jezik, za obični svijet. Eichu ne kažu piši Scheme, ne kažu piši Java-lite, kažu mu: napravi nešto što izgleda kao Java, ali radi kao skripta, i neka bude gotovo do petka. Ono što je Eich zapravo htio napraviti — i ono što je, potajno, ugurao unutra — jest Scheme, funkcionalni jezik, akademski, elegantan, jezik za ljude koji vole zagrade i teoriju. Ono što mu je šef rekao da napravi jest nešto što liči na Javu, jer Java je riječ koja se te godine prodavala sama, kao energetsko piće ili kripto danas. Rezultat je jezik sa Schemeovim srcem u Javinom odijelu, sašiven u deset dana, bez vremena za probnu sobu.

Konačno ime — JavaScript — nema s Javom apsolutno nikakve tehničke veze. Ne dijele sintaksu na način koji bi bilo tko sa zdravim razumom nazvao srodnošću, ne dijele filozofiju, ne dijele ništa osim slova J-a-v-a na početku riječi. To je čisti marketinški parazitizam: zalijepiš popularnu riječ na svoj proizvod da pokupiš njezinu pažnju, kao kad kafić nazove sendvič „Nutella” sendvičem, a Nutelle u njemu ima taman toliko da je za lizanje. Netscape je htio da ljudi pomisle „ovo je vezano za Javu, dakle ozbiljno”, i ta jedna odluka, donesena u sobi za marketing dok je jezik još bio vlažan od pisanja, zbunjuje programere početnike već tri desetljeća. Svako predavanje informatike na svijetu u nekom trenutku mora zastati i objasniti tu razliku, kao da objašnjava zašto kokos nije orah.

Ono što treba shvatiti, prije nego krenemo dalje — Eich nije imao vremena za ono što svaki jezik treba, a to je vrijeme da pogriješiš, pa da to izbrišeš i pokušaš ponovno. Deset dana znači: prva odluka koju napraviš u ponedjeljak, ona koja ti se u srijedu učini glupom, ostaje. Nema druge verzije, nema »popravit ćemo to u 2.0«, jer 2.0 dolazi za preglednik cijeli, ne za jezik unutra. Svaka brzinska prečica koju napraviš pod pritiskom postaje trajni dio jezika koji će, iako to tada nitko nije mogao ni sanjati, jednog dana pokretati pola interneta. Zamisli da moraš napisati zakon države u jednom vikendu, znajući da ga nikad više nećeš smjeti mijenjati — samo dodavati iznimke na iznimke. To je JavaScript. I to ćemo sad, sekciju po sekciju, gledati kako se to slomilo — i kako je, unatoč tome, ili baš zbog toga, pobijedilo.

Genijalno ispod žurbe
§ 02

Genijalno ispod žurbe

Sad, prije nego nastavimo linčati čovjeka, moramo mu priznati zasluge — jer ovo je taj trenutak u priči gdje se otkriva da je deset dana žurbe proizvelo nešto što, ispod haube, uopće nije bilo glupo. Zapravo suprotno. Eich je u tih deset dana ugradio ideje koje su u to doba bile akademska luksuzna roba — stvari koje su se predavale na faksovima uz Scheme i Self, dva tada egzotična jezika koja su živjela u laboratorijima i na doktorskim seminarima, daleko od običnih programera — a ne stvari koje se ubacuju u jezik čija je jedina zadaća bila popunjavanje web formi.

Prvo, funkcije kao građani prvog reda. Zvuči kao fraza koju izgovoriš da impresioniraš na intervjuu, ali suština je jednostavna: funkciju možeš spremiti u varijablu, proslijediti je drugoj funkciji kao argument, vratiti je kao rezultat — tretiraš je identično kao broj ili niz znakova. U jeziku iz 1995., namijenjenom, kao što smo rekli, provjeri je li netko upisao broj telefona s manje od dvanaest znamenki, to je bio hir. Ali taj hir je trideset godina kasnije razlog zašto cijela moderna industrija piše kod u stilu koji zovemo funkcionalnim, zašto React postoji u obliku u kojem postoji, zašto polovica npm paketa uzima funkciju kao argument bez da se nekome to čini čudnim.

Drugo — i ovo je ta ideja koja stvarno zaboli mozak kad je prvi put shvatiš — closures, ili na neki naš način rečeno, 'zatvaranja'. Zamisli funkciju kao kutiju. Ta kutija, kad se stvori, ne zapamti samo što treba izračunati, nego i cijeli kontekst u kojem je rođena — varijable koje su tada postojale, iako je onaj vanjski kod koji ih je stvorio odavno završio i formalno više ne postoji. Funkcija ih drži za rep i ne pušta. Zvuči kao sitnica, dok ne shvatiš da je to mehanizam koji danas stoji ispod pola pametnih trikova u JavaScriptu — od privatnih varijabli do asinkronog koda koji čeka rezultat negdje u budućnosti, a savršeno se sjeća tko ga je pozvao.

Treće — nasljeđivanje kroz prototipove. Umjesto da ima klase, kao normalni jezici tog doba (C++, Java — one iste čiju je odjeću JavaScript morao nositi na modnoj reviji zbog imena), Eich je posudio ideju iz Self-a, egzotičnog istraživačkog jezika koji je malo tko izvan laboratorija ikad vidio: objekti se ne rađaju iz kalupa, nego se kopiraju i nadograđuju jedan od drugoga, kao obiteljsko stablo umjesto fabrike. Danas znamo da je to jedna od stvari koje su generacijama programera zadavale glavobolju — ali i jedna od stvari koja je JavaScript učinila fleksibilnijim nego što je imao pravo biti za jezik pisan u deset dana.

Dakle — budimo pošteni, jer ova enciklopedija nije ovdje da samo pljuje po mrtvima ni po živima. Jezgra jezika, ono što je Eich stvarno smislio, bila je iznenađujuće pametna. Problem, kao što ćemo za koji trenutak vidjeti, nije bio u srcu. Problem je bio u rubovima — u onim tisuću malim odlukama koje se donose kad nemaš vremena provjeriti hoće li se dvije ideje sudariti. A sudarile su se. Spektakularno.

Rubovi katastrofe
§ 03

Rubovi katastrofe

Sad dolazi dio priče gdje se genijalnost naplaćuje. Jer dok je Eich te iste noći ugrađivao closures, i dok je funkcije pretvarao u punopravne građane jezika, pisao je i operator za uspoređivanje dvije vrijednosti — onaj obični, svakodnevni, dvoznak koji svako dijete s osnovne informatike prepozna: `==`. I tu je, umjesto da napravi nešto dosadno i pošteno, odlučio da jezik smije biti — ljubazan. Ako uspoređuješ broj i niz znakova, jezik će ih sam pretvoriti da se poklope. Ako uspoređuješ nešto s `null`, bit će fleksibilan. Zvuči kao usluga. Nije.

Rezultat je tablica istine koja bi trebala biti dosadna aritmetika, a umjesto toga je najbliže što informatika ima horor žanru. `[] == false` je istina. `'' == 0` je istina. `NaN == NaN` je, hvala na pitanju, laž — Not a Number (oznaka za "nije broj", rezultat neuspjelog matematičkog izračuna) nije jednak ni samom sebi, što je filozofski poštenije nego što djeluje. A onaj slavni primjer, onaj koji je desetljećima kolao po konferencijama i predavanjima kao urbani mit informatike — `[] + []` daje prazan string, ali `[] + {}` daje `[object Object]`, dok `{} + []` u konzoli preglednika (onoj skrivenoj alatci gdje programeri ispisuju rezultate svog koda dok traže grešku) daje nulu, jer preglednik to `{}` čita kao prazan blok koda, a ne objekt. Isti znakovi. Tri različita ponašanja, ovisno o tome gdje stoje u redu.

A onda imamo `this`. U većini jezika `this` je predvidljivo dosadno — instanca objekta unutar kojeg se nalaziš, i to je to. U JavaScriptu se `this` određuje u trenutku poziva funkcije, a ne u trenutku njezinog pisanja, što znači da isti komad koda može imati potpuno različit `this` ovisno o tome je li pozvan kao metoda objekta, kao samostalna funkcija, kao rukovatelj događaja (event handler — komad koda koji se pokrene kad korisnik npr. klikne mišem) u pregledniku, ili unutar `setTimeout`-a (naredbe koja odgađa izvršavanje koda za neko vrijeme). Programeri devedesetih i dvijetisućitih naučili su, uz suze, mantru koja se prepisivala s foruma na forum: `var that = this;` na vrhu funkcije, samo da se spasi vrijednost prije nego što je jezik izgubi negdje u dubini poziva. To nije programiranje. To je defenzivna arheologija.

Sad, poštena strana priče: sve ovo nije zato što je Eich bio loš inženjer. Vidjeli smo malo prije — čovjek je za deset dana ugradio ideje koje su druge jezike koštale desetljeća akademskog rada. Problem je što deset dana ne ostavlja vremena za testiranje rubnih slučajeva (onih čudnih, neočekivanih ulaza koje nitko nije predvidio dok je pisao kod), a rubni slučajevi se u JavaScriptu, zbog te iste ljubaznosti prema neurednim podacima s formi, množe kao kunići.

I evo ključnog pitanja koje svaki normalan čovjek postavi kad prvi put čuje ovu priču: ako je jezik toliko poznato čudan, zašto ga jednostavno nisu popravili? Odgovor je isti odgovor koji smo već čuli dvaput u ovoj enciklopediji, iz naizgled nepovezanih konteksta. Sjeti se K1 kartice s bušenim rupicama koja je, jer je netko negdje davno morao donijeti odluku o formatu u roku, diktirala širinu terminala desetljećima poslije toga da je nitko više nije ni vidio. Sjeti se onih 640 kilobajta iz K3 koji su trebali biti privremeno ograničenje, a postali su betonska čizma na nozi cijele industrije. Isti mehanizam, treći put u nizu: web ne smije puknuti. Milijuni stranica već su napisane oslanjajući se na to da `'' == 0` vrati istinu. Popraviš to, i pola interneta se raspadne u tišini, negdje na serveru u Ohiu, i nitko neće znati zašto.

Zato je JavaScript morao naći drugi put — ne popraviti prošlost, nego dodati novu, oprezniju vrata pored starih. Operator „===”, koji ne pretvara ništa i ne oprašta ništa — uspoređuje što jest s onim što jest, bez one ljubazne fleksibilnosti koja pretvara prazan string u nulu — bio je tu od samog početka, čekajući da ga netko koristi. Stara vrata, ona s tablicom istine iz horor žanra, ostala su otvorena, netaknuta, i ostat će otvorena dovijeka — jer je negdje, u nekom kodu kojeg nitko ne dira, netko davno napisao `if (x == null)` i mislio je to ozbiljno.

Od sirotinje do vladara
§ 04

Od sirotinje do vladara

Deset godina. Toliko je JavaScript proveo u podrumu, dok su ozbiljni programeri pisali Javu, C++, možda Perl ako su htjeli biti egzotični. Postojala je rečenica koja se ponavljala po forumima i pušionicama IT tvrtki toliko često da je postala mantra: »pravi programeri ne pišu JavaScript«. Rekli su ti to na faksu. Rekli su ti to na prvom poslu. Netko ti je to rekao na intervjuu, gledajući te preko naočala kao da si upravo priznao da voliš gledati sapunice.

I imao je smisla, taj prezir. Sjećaš se `==` tablice istine od maloprije? Sjećaš se `this`-a koji se ponaša kao pijani rođak na svadbi — nikad ne znaš na koga će se odjednom pozivati? Jezik je bio validacijska guica za formu — provjeri je li netko upisao email, javi mu ružnim alertom da nije, i to je to. Nitko normalan nije zamišljao katedrale od koda u tom alatu. Zašto bi i pokušao? Alat je bio za popravljanje sitnica, ne za građenje kuća.

Onda je 2005. netko sjeo i napisao članak. Jesse James Garrett, dizajner iz agencije Adaptive Path, smislio je kraticu koja će promijeniti sve — AJAX, odnosno Asynchronous JavaScript and XML. Tehnika sama nije bila nova, XMLHttpRequest je tumarao preglednicima od Microsoftove Outlook Web Access ere još od 1999. (cijeli taj most detaljnije je opisan u petoj knjizi, poglavlje 5) — taj alat je, jednostavno rečeno, dopuštao skripti da u pozadini zatraži podatke sa servera bez ponovnog učitavanja cijele stranice. Ali tek su Google Maps i Gmail dokazali svijetu da stranica ne mora osvježiti cijelu sebe da bi ti nešto vratila. Klik, poziv u pozadini, komadić HTML-a se promijeni, i ti to gledaš i misliš: čekaj, kako se to stranica nije trznula?

To se dogodilo u jeziku koji je nastao za deset dana da provjerava kvačice u formama. Odjednom su ljudi pisali čitave aplikacije u toj sirotinjskoj kvačici, i sirotinjska kvačica je to — nevoljko, škripeći, ali — podnosila.

I tu dolazi obrat koji nitko u onoj sobi 1995. nije mogao ni sanjati. Ryan Dahl je 2009. pogledao V8 — motor koji Google ugrađuje u Chrome, program čiji je jedini posao da uzme JavaScript kod i što brže ga pretvori u mašinski jezik koji procesor razumije — izvučen iz preglednika, samostojeći, brz, i pomislio: a što ako ovo pustim da radi izvan browsera? Što ako JavaScript ne ostane zatočen na klijentskoj strani, u tom malom kavezu koji mu je Netscape dodijelio 1995., nego pobjegne na server, gdje su desetljećima vladali Java, PHP i C#? Rezultat se zvao Node.js (cijela priča, s cijelim rođenjem, ima svoje poglavlje u šestoj knjizi), i s njim se dogodila stvar koja je zvučala kao vic dok je netko nije stvarno napravio: isti jezik, ista sintaksa, i na frontendu i na backendu. Jedan programer, jedan mozak, jedna baza znanja, cijela aplikacija.

Zamisli da je netko 1995. rekao Brendanu Eichu: znaš onaj jezik koji si upravo sastavio u deset dana da bi provjeravao je li netko upisao broj kartice u kvačicu na formi? Za petnaest godina će pokretati banke, burze, servere Netflixa, pol interneta. Vjerojatno bi ga pogledao onako kako gledaš čovjeka koji ti na ulici tvrdi da je vidio NLO. A ipak.

Brojke danas nisu suptilne, nego brutalne. Prema godišnjem istraživanju StackOverflowa (najveće svjetske stranice gdje programeri postavljaju pitanja i rješavaju tuđe probleme), JavaScript je već skoro punih deset godina zaredom najkorišteniji jezik na planeti — ne najvoljeniji, budimo pošteni, ali najkorišteniji, što je posve druga kategorija. Na GitHubu, najvećoj svjetskoj ladici u koju programeri spremaju svoj kod (svaki takav 'projekt-folder' zove se repozitorij), JavaScript je godinama broj jedan i po broju tih repozitorija i po broju povlačenja koda (pull requestova). A npm, njegova skladišnica gotovih paketića koda koje možeš samo preuzeti i ugraditi u svoj projekt umjesto da sve pišeš iznova, davno je premašio dva milijuna objavljenih paketa — što znači da za skoro svaki sitni problem koji imaš, negdje postoji netko koji je već napisao rješenje, često loše, ali postoji. Nijedan drugi jezik u povijesti računarstva nije se toliko raširio istovremeno vodoravno (koliko platformi) i okomito (koliko slojeva jedne aplikacije).

Zato je najtočniji opis situacije ovaj: JavaScript nije pobijedio jer je najbolji jezik. Pobijedio je jer je jedini jezik koji je od prvog dana bio ugrađen u svaki preglednik na planetu, i onda je, sretnim nizom tuđih odluka — AJAX-a koji ga je učinio korisnim, V8-a koji ga je učinio brzim, i Node-a koji mu je dopustio da izađe iz preglednika i radi samostalno na serveru — postao i jedini jezik koji radi doslovno svugdje. Na klijentu, na serveru, u mobilnim aplikacijama, u desktop programima, u mikrokontrolerima. Sirotinja iz 1995. sjedi danas na prijestolju, i nitko, baš nitko, tko je to prijestolje dizajnirao, nije to planirao.

Pouka o privremenom
§ 05

Pouka o privremenom

Vratimo se na trenutak na tih deset dana, jer sad ih možemo gledati s druge strane teleskopa. Brendan Eich nije mislio da piše jezik za civilizaciju. Mislio je da piše ljepilo — nešto što će provjeriti je li čovjek upisao broj u polje za broj, i to je to, gotovo, idemo dalje na sljedeći požar. Netscape, tadašnji vodeći internetski preglednik (i tvrtka koja ga je pravila), nije naručio temelj. Naručio je žbuku. I upravo je to razlog zašto je ova priča toliko savršen primjer nečega što ćeš u ovoj enciklopediji sretati iznova i iznova: privremeno rješenje koje nitko nije stigao zamijeniti, pa je postalo vječno. Ne zato što je bilo najbolje. Zato što je bilo tamo prvo, i onda se na njega naslagalo sve ostalo, sloj po sloj, kao koralji na potopljenom brodu — i sad ne možeš izvaditi brod bez da srušiš cijeli greben.

Usporedimo ga, malo zloćudno, s nekim tko je radio sve obrnuto. ALGOL, sjećaš se, iz prve knjige — jezik kojeg su dizajnirali odbori sastavljeni od najboljih glava epohe, s konferencijama, formalnim specifikacijama, godinama raspravljanja o tome je li rekurzija filozofski opravdana. ALGOL je bio pametniji od JavaScripta u svakom mjerljivom smislu. Čišći, dosljedniji, matematički poštenije zamišljen. I ALGOL je mrtav. Ne mrtav kao „nitko ga ne koristi za nove projekte” — mrtav kao „ideje su mu se preselile u desetke drugih jezika, a on sam je postao fusnota koju spominješ na predavanju da zvučiš obrazovano”. Deset dana žurbe nadživjelo je desetljeće posvećenog dizajna. Ako to ne zvuči kao poanta cijele povijesti softvera, ne znam što bi bilo.

I tu dolazimo do žulja koji svaki webdeveloper osjeti već prvi tjedan posla: `undefined is not a function`, `0 == '0'` je istina, a `[] == ![]` je isto istina (nije šala, provjeri kad stigneš doma), zatvaranja (closures) i prototipovi koji rade genijalno dok ih ne krivo upotrijebiš, pa se sve raspadne u tišini, bez upozorenja. To nije slučajna okrutnost jezika prema tebi. To je fosilizirana žurba iz svibnja 1995., zamrznuta u ime kompatibilnosti jer web ne smije puknuti. Svaki put kad otvoriš konzolu i vidiš crvenu poruku koja nema smisla, rukuješ se s odlukom koju je jedan čovjek donio prije nego što je stigao popiti drugu kavu, tog dana, u tom tjednu, davno.

Ali evo i utjehe, jer ova knjiga voli udariti pa pomilovati, u istom dahu. Svijet se ne vrti oko najboljeg koda. Svijet se vrti oko koda koji je bio tamo u utorak, kad je bio potreban, spreman odraditi posao dok su svi ostali još crtali dijagrame na ploči. JavaScript je uvijek bio taj kod. Ružan, hitan, pun rupa koje ćeš pronaći tek kad te najviše zaboli — i uvijek, uvijek tamo u pravi trenutak, spreman preuzeti sljedeći zadatak koji mu nitko pametan nije namijenio. Prvo forme. Onda AJAX. Onda V8, koji je jezik ubrzao preko svakog očekivanja, i brzina koju nitko nije očekivao od „jezika za formice” postala je stvarnost. Onda Node, koji je taj isti jezik izvukao iz pretraživača i posjeo ga na server, pa JavaScript odjednom trči i tamo gdje mu, formalno, nikad nije bilo mjesto. Svaki put netko je rekao „ovo sigurno ne može”, i svaki put je JavaScript samo, šutke, odradio posao.