Co to jest JavaScript?

JavaScript

JavaScript to język programowania, który powstał w 1995 roku jako prosty kliencki język skryptowy dla przeglądarki Netscape Navigator, ale przeistoczył się w jeden z głównych filarów sieci Sieci Światowej (ang. World Wide Web) (razem z HTML oraz CSS), którego wykorzystanie rozszerzyło się na stronę serwerową (przede wszystkim ze względu na powstanie środowiska uruchomieniowego używanego po stronie serwera Node.js). Pomimo tego, że JavaScript zaczął jako przedsięwzięcie jednej firmy, teraz jest powszechnie używany, większość głównych przegląderek ma wbudowane śrowiska uruchomieniowe JavaScript, a Ecma International standaryzuje jego wersje.

Wprowadzenie

Z punktu widzenia technologicznego, JavaScript jest językiem programowania, który:

Początki JavaScript

W 1993 roku, przeglądarka NCSA Mosaic, utworzona w National Center for Supercomputing Applications przy Uniwersytecie Illinois, została wydana. Stała się pierwszą powszechnie używaną przeglądarką dostępną na systemie operacyjnym Windows, która integrowała tekst i grafikę. Wspierała wiele protokołów internetowych takich jak HTTP, czyli Protokół Przesyłania Dokumentów Hipertekstowych (ang. Hypertext Transfer Protocol) oraz FTP, czyli Protokół Przeysłania Plików (ang. File Transfer Protocol), ale nie zawierała języka skryptowego podobnego do JavaScript. Microsoft wylicencjował jedną z wersji Mosaic w 1995 roku i zbudował Internet Explorer na jej podstawie.

W 1994 roku, główny deweloper Mosaic utworzył przeglądarkę Netscape Navigator, która szybko stała się popularna. W roku 1995, zdecydowano się dodać język skryptowy do Netscape Navigator, aby umożliwić dynamiczną modyfikację dokumentów. Jednym z pomysłów było użycie języka Java we współpracy z Sun Microsystems, innym wbudowanie języka Schema. Jednakże, finalnie, zdecydowano się na utworzenie nowego. Zadanie to zostało powierzone Brendanowi Eich.

Nowo-powstały język skryptowy nazwany został LiveScript w jednej z beta iteracji przeglądarki Netscape, ale nazwa została zmieniona na JavaScript w oficjalnym wydaniu. Pierwsza oficjalna wersja Netscape Navigator, która zawierała JavaScript została wydana w 1995 roku.

Microsoft również wydał swoją przeglądarkę, Internet Explorer, w roku 1995. Internet Explorer zawierał JScript, którego program interpretujący (ang. interpreter) był poddany inżynierii odwrotnej (ang. reverse-engineered) z Netscape Navigator. Tym samym marsz do powszechności JavaScript jako głównego języka skryptowego sieci rozpoczął się.

Standaryzacja JavaScript przez Ecma

Około jeden rok po oficjalnym debiucie, Netscape przedłożył JavaScript do Ecma Inernational do standaryzacji.

Pierwsza wersja JavaScript standaryzowana przez Ecma International nazwana została ECMAScript (ES1) i została wydana w roku 1997.

Druga standaryzowana wersja JavaScript, nazwana ECMAScript 2 (ES2), została wydana w roku 1998.

Trzecia standaryzowana wersja JavaScript, nazwana ECMAScript 3 (ES3) została wydana w roku 1999.

Początkowo, Microsoft oraz jego przeglądarka Internet Explorer stosowali się do standaryzacji Ecma, ale później jego współpraca ustała. Z uwagi na przeważający ówczesny udział w rynku przeglądarek Internet Explorer, spowodowało to, że czwarta wersja standaryzowanego JavaScript (ES4) nigdy nie została wydana.

Dominacja Microsoft na rynku przeglądarek wczesnych lat dwutysięczncyh została złamana wydaniem w roku 2004 następcy Netscape Navigator'a, Firefox, oraz wydaniem w roku 2008 Google Chrome. Google Chrome zawierał szybki silnik uruchomieniowy (ang. runtime engine) - V8. Obie przeglądrki przejęły duże części rynku. Potrzeba standaryzacji pojawiła się na nowo.

Wspólny wysiłek zainteresowanych stron oraz Ecma International doprowadził do wydania epokowych wersji JavaScript, a mianowicie ECMAScript 5 (ES5) w roku 2009 oraz ECMAScript 6 (ES6) w roku 2015.

Kolejne wersje JavaScript oznaczane są raczej rokiem wydania, niż numerem. Dlatego, po ES6, wersje ECMAScript nazwane zostały ECMAScript 2016, ECMAScript 2017, ECMAScript 2018, ECMAScript 2019, etc. Jednakże, numeryczne wersje, ES7, ES8, ES9, ES10, również czasem są używane.

JavaScript jako kliencki język programowania

Jak nakreślono powyżej, JavaScript powstał jako język programowania wbudowany w program kliencki (ang. user-agent), w przeglądarkę.

Dziś, JavaScript jest głównym i najbardziej rozpowszechnionym klienckim językiem programowania Sieci Światowej (ang. World Wide Web).

Po stronie klienta JavaScript może być używany między innymi do:

  • manipulowania Obiektowym Modelem Dokumentu (ang. Document Object Model), to jest do dodawania, zmiany, oraz usuwania elementów dokumentów w przeglądarkach, oraz

  • pobierania danych ze zdalnych hostów (komputerów).

Aby ułatwić tworzenie oprogramowania w JavaScript po stronie klienta powstało wiele bibliotek i frameworków. Obecnie, jedne z najpopularniejszych z nich to:

  • React stworzony przez Facebook,

  • Angular stworzony przez Google,

  • Vue.js stworzony przez Evan You, oraz

  • jQuery stworzony przez John Resig.

JavaScript jako serwerowy język programowania

Pomimo tego, że JavaScript rozpoczął swoje życie jako kliencki (wbudowany w przeglądarkę) język skryptowy, to obecnie jest również powszechnie używany jako język serwerowy

Popularność JavaScript jako języka serwerowego rozpoczęła się wraz z utworzeniem Node.js w roku 2009 przez Ryan Dahl'a.

Node.js używa pod spodem silnika JavaScript V8 stworzonego przez Google. Node.js zawiera pętle wydarzeń (ang. event loop) oraz interfejsy I/O (wejścia i wyjścia).

Domyślny menadżer paczek dla Node.js zwany jest npm.

Jest wiele serwerowych bibliotek i frameworków JavaScript, które ułatwiają tworzenie programowania. Niektóre godne uwagi, to:

  • Express stworzony przez TJ Holowaychuk,

  • Next.js stworzony przez Guillermo Rauch i rozwijany przez Vercel, oraz

  • NestJS stworzony przez Kamila Myćliwca.

JavaScript jako wysokopoziomowy język programowania

JavaScript jest wysokopoziomowym językiem programowania (ang. high-level programming language).

Wysokopoziomowy język programowania

Wysokopoziomowy język programowania to język programowania, który nie wymaga bezpośredniego zarządzania sprzętem komputerowym (np. zarządzania pamięcią), ale jest zdolny do automatyzacji takiego zarządzania, gdy jest taka potrzeba, poprzez wbudowane procedury, i, tym samym, umożliwia łatwiejsze i szybsze tworzenie oprogramowania.

JavaScript jako kompilowany na bieżąco język programowania

JavaScript jest językiem programowania kompilowanym na bieżąco (ang. just-in-time compiled).

Kompilowany na bieżąco język programowania

Kompilowany na bieżąco język programowania to język programowania, w którym kod źródłowy jest kompilowany do kodu maszynowego w częściach podczas wykonywania tych części, zamiast stosowania kompilacji poprzedzającej (ang. ahead-of-time compilation). Ogólnie, kompilacja na bieżąco łączy szybkość kompilacji poprzedzającej z elastycznością interpretacji.

JavaScript jako słabo-typowany język programowania

JavaScript jest często opisywany jako słabo-typowany (ang. weakly typed) język programowania.

Jednakże, istnieje wiele różnych definicji czym słabo-typowany język programowania rzeczywiście jest.

Gdy opisywany jest JavaScript jako słabo-typowany język, to przez to często rozumiane są zdolności JavaScript do domyślnej zmiany typów (ang. implicit casting) swych wartości w niektórych ze swoich wbudowanych operatorów.

Na przykład, gdy porównujemy dwie wartości o różnych typach danych używając ==, czyli operatora porównywania abstrakcyjnego (ang. abstract comparison operator), to typy tych wartości są domyślnie zmieniane na spójne przed samym porównaniem.

1 == "1" // => true

Innym przykładem jest domyślna zmiana typu obu operandów na słowo (ang. string), gdy którykolwiek z tych operandów jest liczbą, przez operator binarny +.

1 + "1" // => "11"

Jeszcze innym przykładem jest domyślna zmiana typów obu operandów na liczbę (ang. number), gdy którykolwiek z tych operandów nie jest liczbą, przez operator binarny -.

1 - "1" // => 0

JavaScript jako dynamicznie typowany język programowania

JavaScript jest dynamicznie typowanym (ang. dynamically typed) językiem programowania.

Dynamicznie typowany język programowania

Dynamicznie typowany język programowania to język programowania, w którym typ identyfikatora (takiego jak zmienna) jest wywodzony przez interpretator podczas wykonywania i może się dynamicznie zmieniać podczas tego wykonywania, w przeciwieństwie do bycia statycznie ustalonym (wprost lub w sposób dorozumiany) przed komiplacją poprzedzającą.

// JavaScript (dynamiczne typowanie)
let foo = 42
foo = "czterdzieści dwa" // Zmiana z liczby na słowo dozwolona.
// TypeScript (statyczne typowanie)
let foo = 42 // typ foo statycznie w sposób dorozumiany ustalony jak 'liczba'.
foo = "czterdzieści dwa" // Typ 'słowo' nie może zostać przypisany do typu 'liczba'.

JavaScript jako język programowania oparty na prototypach

Od swojego początku w roku 1995, JavaScript jest językiem programowania opartym na prototypach.

Język programowania oparty na prototypach

Język programowania oparty na prototypach to obiektowy język programowania, w którym obiekt może dziedziczyć właściwości (ang. properties) drugiego obiektu poprzez a) ustawienie tego drugiego obiektu jako prototypu oraz delegowanie wezwań tych właściwości do tego drugiego obiektu (prototypowanie oparte na delegacji), lub b) kopiowanie właściwości tego drugiego obiektu (prototypowanie konkatenacyjne), oraz w przeciwieństwie do dziedziczenia tych właściwości przez instancjanowanie specjalnie dedykowanych konstruków zwanych klasami.

JavaScript implementuje prototypowanie oparte na delegacji.

const czlowiek = { zawod: 'pracowanie', rzad: 'ssaki naczelne' }
const student = { imie: 'Dawid', zawod: 'studiowanie' }

Object.setPrototypeOf(student, czlowiek)

student.imie // => 'Dawid'
student.zawod // => 'studiowanie'
student.rzad // => 'ssaki naczelne'

Czytaj dalej w Dziedziczenie oparte na prototypach w JavaScript.

JavaScript jako język programowania oparty na klasach

Począwszy od ECMAScript 2015 (ES6), JavaScript jest językiem programowania opartym na klasach.

Język programowania oparty na klasach

Język programowania oparty na klasach to obiektowy język programowania, w którym obiekt może dziedziczyć właściwości od szczególnie dedydkowanego dla dziedziczenia konstruktu zwanego klasą (która sama może, ale nie musi, być obiektem), i w przeciwieństwie do dziedziczenia właściwości od obiektu niebędącego klasą.

class Pies {
  constructor(imie) {
    this.imie = imie
  }

  szczekaj() {
    console.log('Hau!')
  }
}

const pluto = new Pies('Pluto')

pluto.imie // => 'Pluto'
pluto.szczekaj() // 'Woof!'

Czytaj dalej w Dziedziczenie oparte na klasach w JavaScript.

JavaScript jako obiektowy język programowania

JavaScript jest obiektowym językiem programowania.

Obiektowy język programowania

Obiektowy język programowania to język programowania, który zawiera obiekty, czyli konstrukty programistyczne, które a) mają unikalną tożsamość, b) zawierają dane (często wspólnie zwane stanem) oraz procedury (często zwane metodami), które łacznie określa się właściwościami (ang. properties), oraz które c) mogą dziedziczyć takie właściwości od szczególnie dedykowanych dziedziczeniu konstruktów zwanych klasami (które mogą, ale nie muszą, same być obiektami) lub od innych obiektów nieklasowych, które zwane są wtedy prototypami.

const pirat = {
  imie: 'Hook',
  okrzyk: function() { console.log('Huzzah!') }
}

pirat.imie // => 'Hook'
pirat.okrzyk() // 'Huzzah!'

Jednakże, JavaScript nie jest obiektowym językiem programowania w pełni (tak jak jest np. Ruby), gdyż wciąż zawiera wartości pierwotne (ang. primitive values), takie jak liczby (ang. numbers), słowa (ang. strings), oraz wartości logiczne (ang. booleans), które nie mają stanu, ani metod z nimi powiązanych.

JavaScript jako funkcyjny język programowania

JavaScript jest funkcyjnym językiem programowania.

Funkcyjny język programowania

Funkcyjny język programowania jest językiem programowania, w którym funkcje mogą być przypisywane do identyfikatorów, takich jak zmienne, przekazywane jako argumenty innych funkcji, oraz zwracane jako wartości z innych funkcji.

Gdy funkcje mają zdolności do bycia przypisywanym do identyfikatorów, do bycia przekazywanym jako argumenty, oraz bycia wartościami zwrotnymi innych funkcji, to często określa się je obywatelami pierwszej klasy (ang. first-class citizens).

JavaScript może wykorzystywać dwa wzorce programowania funkcyjnego:

  • nieczyste programowanie funkcyjne, oraz

  • czyste programowanie funkcyjne.

Nieczyste programowanie funkcyjne to programowanie funkcyjne:

  • które może polegać na wartościach spoza zakresu (ang. scope) funkcji i tym samym zwracać różne wartości, gdy podane są te same argumenty, oraz,

  • w których wykonanie funkcji może mieć efekty uboczne (ang. side effects) takie jak modyfikacje wartości spoza zakresu tej funkcji.

Czyste programowanie funkcyjne (ang. pure functional programming) to programowanie funkcyjne:

  • które nie może polegać na wartościach spoza zakresu (ang. out-of-scope) funkcji i tym samym zawsze zwraca te same wartości przy podaniu tych samych argumentów,

  • w których wykonanie funkcji nie może mieć efektów ubocznych takich jak modyfikacja wartości spoza zakresu tej funkcji.

JavaScript jako imperatywny język programowania

JavaScript może być używany jako imperatywny język programowania.

Imperatywny język programowania

Imperatywny język programowania to język programowania, który używa sekwencji rozkazów (ang. commands) - w Łacinie imperare znaczy rozkazywać - aka instrukcji (ang. statements), z których każdy wskazuje szczególne działanie, które ma zostać podjęte, i które może bezpośrednio zmienić stan danego procesu.

let wiek = 42
const czujeSieMlodo = true

if (czujeSieMlodo) {
  wiek = wiek / 2
}

JavaScript jako sterowany wydarzeniami język programowania

JavaScript może być używany jako sterowany wydarzeniami (ang. event driven) język programowania.

Sterowany wydarzeniami (ang. event driven) język programowania

Sterowany wydarzeniami (ang. event driven) język programowania to język programowania, w którym kontrola przepływu (ang. control flow) procesu danego programu determinowana jest wydarzeniami uruchamianymi przez a) komunikaty (ang. messages) z samego procesu, b) komunikaty z innych procesów, lub c) interakcje użytkownika (naciśnięcia klawiszy, kliknięcia myszy, przewijanie myszą, etc.).

// Loguje "kliknięto okno!" za każdym razem, gdy okno przeglądarki jest kliknięte.
const zalogujKlinieteOkno = () => console.log('kliknięto okno!')
window.addEventListener('click', zalogujKlinieteOkno, false)