JavaScript — język programowania, który stał się podstawą całej klasy hybrydowych technologii mobilnych. React Native, Ionic, Apache Cordova i wiele innych frameworków pozwala tworzyć aplikacje mobilne w JS, wykorzystując jednolity stos technologii z tworzeniem stron internetowych. JavaScript pozostaje najczęściej używanym językiem programowania dziesiąty rok z rzędu według ankiety Stack Overflow (2025). Więcej informacji znajdziesz w wynikach ankiety Stack Overflow.
Najważniejsze
JavaScript (JS) — język programowania wysokiego poziomu z dynamicznym typowaniem, prototypowym dziedziczeniem i funkcjami jako obiektami pierwszej klasy. Stworzony przez Brendana Eicha w 1995 roku w 10 dni. Jest jednym z trzech głównych języków technologii internetowych (HTML, CSS, JS) i podstawą platformy serwerowej Node.js (2009), która pozwoliła JS wyjść poza przeglądarkę.
W tworzeniu aplikacji mobilnych JavaScript jest używany w trzech paradygmatach: natywna kompilacja (React Native z Hermes/JSC), kontenery WebView (Ionic, Cordova) i serwerowy JS (Node.js + Express dla backendu aplikacji mobilnych). React Native — dominująca technologia: według Statista (2025), 38% projektów wieloplatformowych używa React Native, ustępując tylko Flutter (46%).
Kluczowa cecha JavaScript — jednowątkowy model wykonania z nieblokującym wejściem-wyjściem. Event loop pozwala przetwarzać tysiące operacji asynchronicznych w jednym wątku bez tworzenia wątków systemu operacyjnego. To czyni JS wydajnym dla aplikacji obciążonych I/O (zapytania sieciowe, praca z bazami danych), ale wymaga ostrożności przy obliczeniach intensywnie wykorzystujących CPU.
Standard ECMAScript (ES) definiuje specyfikację JavaScript. ES6 (2015) wprowadził let/const, funkcje strzałkowe, klasy, moduły, Promise. ES2020 — Optional Chaining (?.), Nullish Coalescing (??). ES2023 — Array findLast, Hashbang Grammar. Nowoczesne silniki Hermes (React Native) i V8 (Node.js) obsługują ES2022+. React Native Hermes obsługuje ES2020+ z pewnymi ograniczeniami dotyczącymi Proxy i Symbol.
| Wersja ES | Rok | Kluczowe funkcje | Wsparcie RN |
|---|---|---|---|
| ES6 | 2015 | let/const, Promise, class, modules, arrow functions | Pełne |
| ES8 | 2017 | async/await, Object.entries | Pełne |
| ES2020 | 2020 | Optional Chaining, Nullish Coalescing, BigInt | Pełne |
| ES2022 | 2022 | Top-level await, .at(), Error Cause | Hermes ograniczone |
Składnia JavaScript — podobna do C, dynamicznie typowana. Typ zmiennej jest określany przez wartość i może zmieniać się w runtime. let i const (ES6) zastąpiły var dla blokowego zakresu widoczności. Typy prymitywne: string, number, boolean, null, undefined, symbol, bigint. Cała reszta to obiekt (object, array, function, date, regexp).
JavaScript — język z funkcjami wyższego rzędu. Funkcje można przypisywać do zmiennych, przekazywać jako argumenty, zwracać z innych funkcji. Funkcje strzałkowe (=>) nie mają własnego this — dziedziczą this z zewnętrznego kontekstu. Domknięcie (closure) — funkcja zapamiętująca zmienne z zakresu widoczności, w którym została utworzona.
// Typy danych i funkcje w JavaScript
// Typy prymitywne
const name = 'React Native';
let version = 0.71;
var isActive = true; // przestarzały var
// Obiekty i tablice
const app = {
platform: 'iOS',
version: 15,
getInfo() {
return `${this.platform} ${this.version}`;
}
};
const items = ['Dart', 'Kotlin', 'Swift'];
// Funkcja wyższego rzędu
function filterByVersion(apps, minVersion) {
return apps.filter(app => app.version >= minVersion);
}
// Domknięcie (closure)
function createCounter() {
let count = 0;
return function() {
return ++count;
};
}
const counter = createCounter();
console.log(counter()); // 1
console.log(counter()); // 2
// Operator spread do kopiowania obiektów
const newApp = { ...app, version: 16 };Operator spread ... tworzy płytką kopię obiektu. Destrukturyzacja (const { platform, version } = app) wyodrębnia pola do zmiennych. Funkcja strzałkowa w filterByVersion jest krótsza niż wyrażenie function i nie tworzy własnego this — jest to krytyczne w komponentach React Native, gdzie this odnosi się do klasy komponentu.
JavaScript używa dziedziczenia prototypowego, a nie klasowego jak Java czy C#. Klasy (ES6) — cukier składniowy na bazie prototypów. Każdy obiekt ma wewnętrzne odniesienie [[Prototype]] do innego obiektu. Przy dostępie do właściwości, której nie ma w obiekcie, JS szuka jej w łańcuchu prototypów. Składnia klasowa (extends, super) czyni kod bardziej czytelnym, ale pod spodem pozostają prototypy.
// Klasy w JavaScript — cukier składniowy
class PlatformService {
// Pole prywatne (ES2022)
#apiKey;
constructor(name, apiKey) {
this.name = name;
this.#apiKey = apiKey;
}
// Metoda statyczna
static getPlatforms() {
return ['iOS', 'Android'];
}
// Getter
get info() {
return `${this.name} SDK`;
}
// Metoda asynchroniczna
async initialize() {
return await this.#validateKey();
}
#validateKey() {
return this.#apiKey.length > 10;
}
}
// Dziedziczenie
class AndroidService extends PlatformService {
constructor(apiKey) {
super('Android', apiKey);
}
}Prywatne pola #apiKey (ES2022) zapewniają prawdziwą enkapsulację, niedostępną przy konwencjach z _underscore. Metoda statyczna getPlatforms należy do klasy, a nie do instancji. Getter info jest obliczany przy dostępie. async/await czyni kod asynchroniczny liniowym. React Native Hermes obsługuje prywatne pola od wersji 0.71.
Asynchroniczność JavaScript opiera się na event loop — nieskończonej pętli, która sprawdza stos wywołań (call stack) i kolejki zadań. Call stack — kod synchroniczny, microtask queue — Promise.then/catch/finally, macrotask queue — setTimeout, setInterval, I/O. Event loop pobiera zadania najpierw z microtask, następnie z macrotask. Zablokowanie call stack (nieskończona pętla) zatrzymuje cały UI.
Promise — obiekt reprezentujący przyszłą wartość. Promise może być pending (oczekiwanie), fulfilled (sukces), rejected (błąd). Łańcuch .then().catch().finally() obsługuje wynik asynchroniczny. async/await (ES8) — cukier składniowy: funkcja async zwraca Promise, await wstrzymuje wykonanie do rozstrzygnięcia promise, nie blokując wątku.
// Asynchroniczne ładowanie danych w React Native
import React, { useState, useEffect } from 'react';
import { View, Text, ActivityIndicator } from 'react-native';
function UserProfile({ userId }) {
const [user, setUser] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
let cancelled = false;
async function fetchUser() {
try {
const response = await fetch(
`https://api.example.com/users/${userId}`
);
if (!response.ok) {
throw new Error('Network error');
}
const data = await response.json();
if (!cancelled) {
setUser(data);
setLoading(false);
}
} catch (error) {
if (!cancelled) {
console.error('Fetch failed:', error);
setLoading(false);
}
}
}
fetchUser();
return () => { cancelled = true; };
}, [userId]);
if (loading) return <ActivityIndicator />;
return (
<View>
<Text>{user?.name ?? 'Unknown'}</Text>
</View>
);
}Hook useEffect z funkcją async fetchUser wykonuje zapytanie HTTP przy montowaniu komponentu. Flaga cancelled zapobiega setState po odmontowaniu — częsty problem w React Native. Optional Chaining user?.name i Nullish Coalescing ?? obsługują undefined bez błędów. ActivityIndicator wyświetla się podczas ładowania — wzorzec asynchroniczny znany każdemu programiście JS.
React Native — framework od Meta (Facebook) do tworzenia natywnych aplikacji mobilnych w JavaScript. W przeciwieństwie do podejścia WebView, React Native renderuje prawdziwe natywne komponenty (UIView dla iOS, ViewGroup dla Android). Kod JS jest wykonywany w osobnym wątku (Hermes lub JSC) i komunikuje się z natywnym wątkiem UI przez Bridge (stara architektura) lub JSI (nowa architektura Fabric).
React Native składa się z wątku JS (twój kod), wątku natywnego (UI) i Bridge/JSI do ich komunikacji. W starej architekturze (Bridge) wiadomości JSON są serializowane i przesyłane asynchronicznie — powoduje to opóźnienia przy szybkich animacjach. Nowa architektura Fabric (React Native 0.68+) używa JSI (JavaScript Interface) — bezpośrednia interakcja JS z obiektami C++ bez serializacji.
// Komponent React Native z natywnym API
import React, { useState, useEffect } from 'react';
import {
View, Text, TouchableOpacity, Platform,
PermissionsAndroid, Alert
} from 'react-native';
import Geolocation from '@react-native-community/geolocation';
function LocationTracker() {
const [location, setLocation] = useState(null);
useEffect(() => {
requestLocationPermission();
}, []);
async function requestLocationPermission() {
if (Platform.OS === 'android') {
const granted = await PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION
);
if (granted !== PermissionsAndroid.RESULTS.GRANTED) {
Alert.alert('Permission denied');
return;
}
}
getCurrentPosition();
}
function getCurrentPosition() {
Geolocation.getCurrentPosition(
pos => setLocation({
lat: pos.coords.latitude,
lng: pos.coords.longitude
}),
error => Alert.alert('Error', error.message),
{ enableHighAccuracy: true, timeout: 15000 }
);
}
return (
<View>
<Text>Lat: {location?.lat ?? 'N/A'}</Text>
<Text>Lng: {location?.lng ?? 'N/A'}</Text>
<TouchableOpacity onPress={getCurrentPosition}>
<Text>Update Location</Text>
</TouchableOpacity>
</View>
);
}Komponent LocationTracker demonstruje pracę z natywnym API geolokalizacji. Platform.OS rozróżnia Android i iOS. PermissionsAndroid.request — natywne okno dialogowe uprawnień Android. Geolocation.getCurrentPosition — moduł @react-native-community/geolocation, instalowany przez npm. React Native udostępnia JS-interfejsy dla kamery, Bluetooth, akcelerometru i innych czujników.
Ionic — framework do hybrydowych aplikacji mobilnych, używający WebView do renderowania HTML/CSS/JS. W przeciwieństwie do React Native, Ionic nie tworzy natywnych komponentów — aplikacja działa wewnątrz kontenera internetowego (WebView) na iOS (WKWebView) i Android (Android WebView). Daje to 100% ponowne wykorzystanie kodu internetowego, ale ogranicza wydajność przy złożonych animacjach.
Apache Cordova — podstawa Ionic, zapewniająca dostęp do natywnych API przez wtyczki JavaScript. Aparat, GPS, kontakty, system plików — wszystko dostępne przez cordova-plugin-*. Ionic 7+ używa Capacitor — następcy Cordova z lepszą wydajnością, obsługą ESM i bezpośrednim dostępem do iOS/Android SDK przez Swift i Kotlin.
| Cecha | React Native | Ionic (Capacitor) | Cordova |
|---|---|---|---|
| Renderowanie UI | Natywne komponenty | WebView (WKWebView) | WebView |
| Język | JS/TS | JS/TS + HTML/CSS | JS/TS + HTML/CSS |
| Natywne API | Bridge/JSI + moduły | Capacitor Plugins | Cordova Plugins |
| Wydajność | Wysoka (60 FPS) | Średnia (zależy od WebView) | Średnia |
| Rozmiar APK | ~25-40 MB | ~10-15 MB | ~8-12 MB |
| Ponowne użycie | ~60% kodu | ~95% kodu z wersją webową | ~95% |
Narzędzia programisty JS dla aplikacji mobilnych obejmują Node.js, npm/yarn, Expo, React Native CLI i Metro bundler. Node.js — środowisko wykonawcze JS poza przeglądarką, podstawa ekosystemu. npm (Node Package Manager) — menedżer pakietów z 2+ milionami bibliotek. npx — narzędzie do uruchamiania pakietów npm bez instalacji.
Expo — nakładka na React Native, upraszczająca tworzenie: nie wymaga Xcode/Android Studio do rozpoczęcia, zapewnia Managed Workflow z preinstalowanymi bibliotekami. Expo Application Services (EAS) — budowanie i publikowanie w chmurze. Metro — bundler React Native, zbierający kod JS i zależności w jeden plik. Hermes — silnik JS od Meta, zoptymalizowany dla urządzeń mobilnych z kompilacją AOT.
// package.json — konfiguracja projektu React Native
{
"name": "MyMobileApp",
"version": "1.0.0",
"scripts": {
"start": "npx react-native start",
"android": "npx react-native run-android",
"ios": "npx react-native run-ios",
"test": "jest",
"lint": "eslint . --ext .ts,.tsx"
},
"dependencies": {
"react": "^18.2.0",
"react-native": "^0.73.0",
"@react-navigation/native": "^6.1.0",
"@react-native-community/geolocation": "^3.2.0"
},
"devDependencies": {
"jest": "^29.7.0",
"eslint": "^8.56.0",
"metro-react-native-babel-preset": "^0.77.0"
}
}Plik package.json — podstawa każdego projektu JS. Skrypty start, android, ios uruchamiają bundler Metro i budowanie. Zależności są podzielone na dependencies (runtime) i devDependencies (testy, lintery). React Navigation — standardowy router. Jest — framework do testowania. ESLint — statyczny analizator, sprawdzający styl kodu i potencjalne błędy.
Często zadawane pytania
JavaScript (JS) — język programowania z dynamicznym typowaniem, prototypowym dziedziczeniem i jednowątkowym modelem event loop. Stworzony w 1995 roku. W tworzeniu aplikacji mobilnych używany przez React Native (natywne komponenty + logika JS) i Ionic (kontener WebView). Jest najczęściej używanym językiem dziesiąty rok z rzędu według Stack Overflow.
React Native wykonuje JS w osobnym wątku (Hermes lub JSC). Wątek JS zarządza logiką i stanem, wątek natywny renderuje komponenty UI. Wymiana danych — przez Bridge (stara architektura, serializacja JSON) lub JSI (nowa architektura Fabric, bezpośredni dostęp C++). Hermes — silnik JS od Meta z kompilacją AOT, zmniejszający czas uruchamiania o 50%.
JavaScript — dynamicznie typowany, typy są sprawdzane w runtime. TypeScript dodaje statyczne typowanie ze sprawdzaniem na etapie kompilacji, interfejsy, generyki i wyliczenia. Każdy kod JS jest poprawnym kodem TypeScript. TS jest kompilowany (transpilowany) do czystego JS przez tsc lub Babel. W React Native TS jest używany w ~65% nowych projektów.
Główne: React Native (Meta) — natywna platforma renderująca z Bridge/Fabric. Ionic (Capacitor) — kontener WebView z dostępem do natywnych API przez wtyczki. Apache Cordova — poprzednik Ionic, również WebView. NativeScript — bezpośredni dostęp do natywnych API bez WebView. Expo — nakładka na React Native do szybkiego prototypowania bez natywnej kompilacji.
Asynchroniczność JS opiera się na event loop: call stack (kod synchroniczny) → microtask queue (Promise.then) → macrotask queue (setTimeout, I/O). Promise — obiekt dla operacji asynchronicznych. async/await — cukier składniowy nad Promise. Model jednowątkowy nie blokuje UI, ale zadania intensywne CPU wymagają Web Workers lub osobnego wątku (w React Native — InteractionManager).
Podsumowanie
Opracujemy aplikację mobilną pod klucz
IT Sectr tworzy aplikacje na iOS i Androida dla startupów i firm od 2017 roku. Doradzimy Ci i zaproponujemy najlepsze rozwiązanie.
Przeczytaj również