Základy programovania v JavaScripte

Záverečná lekcia

Milan Herda, 03/2023

Čo nás dnes čaká

  • vybrané vlastnosti z ES2015
  • opakovanie
  • tipy na štúdium
  • kde sa dajú využiť znalosti
  • vyrobíme si certifikát

Vybrané vlastnosti z JS verzie ES2015

Arrow funkcie

  • kratší zápis
  • uchovávanie kontextu (this, arguments)

Arrow funkcie - kratší zápis

var pow = function (arg) {
    return arg * arg;
};
const pow = (arg) => {
    return arg * arg;
};
const pow = (arg) => arg * arg;
// Pozor, zátvorky okolo argumentov sa dajú odobrať
// iba v prípade jednoargumentovej funkcie
// Funkcia bez argumentov musí mať zátvorky uvedené!
const getName = () => 'zelenina';
const pow = arg => arg * arg;

Arrow funkcie - zdieľanie kontextu

const tyrion = {
    name: 'tyrion',
    tags: ['piť', 'nadávať', 'veci'],

    printKnowledge: function () {
        this.tags.forEach(function (tag) {
            console.log(this.name + ' vie ' + tag);
        });
    }
};

tyrion.printKnowledge();

Skúste tento kód opraviť v starom JS (bez arrow funkcie)

Arrow funkcie - zdieľanie kontextu

const tyrion = {
    name: 'tyrion',
    tags: ['piť', 'nadávať', 'veci'],

    printKnowledge: function () {
        const that = this;

        this.tags.forEach(function (tag) {
            console.log(that.name + ' vie ' + tag);
        });
    }
};

tyrion.printKnowledge();

Starý JS: pomocná premenná "that"

Arrow funkcie - zdieľanie kontextu

const tyrion = {
    name: 'tyrion',
    tags: ['piť', 'nadávať', 'veci'],

    printKnowledge: function () {
        this.tags.forEach((tag) => {
            console.log(this.name + ' vie ' + tag);
        });
    }
};

tyrion.printKnowledge();

Nový JS: array funkcia

Rozšírené objektové literály

const name = 'Ferko';
const lastName = 'Mrkvička';
const x = 'abc';
const y = 'def';

const fero = {};

/* Pre objekt fero:
 * - vytvorte property name a lastName,
 *   ktoré budú mať hodnoty z premenných vyššie
 * - vytvorte metódu foo, ktorá vráti reťazec 'metóda foo'
 * - vytvorte property, ktorej názov je poskladaný z x a y.
 */

console.log(fero.name);
console.log(fero.lastName);
console.log(fero.foo());
console.log(fero.abcdef);

Rozšírené objektové literály

const name = 'Ferko';
const lastName = 'Mrkvička';
const x = 'abc';
const y = 'def';

const fero = {
    name: name,
    lastName: lastName,
    
    // vytvorte metódu foo, ktorá vráti reťazec 'metóda foo'
    // vytvorte property, ktorej názov je poskladaný z x a y.
};

console.log(fero.name);
console.log(fero.lastName);
console.log(fero.foo());
console.log(fero.abcdef);

V starom JS

Rozšírené objektové literály

const name = 'Ferko';
const lastName = 'Mrkvička';
const x = 'abc';
const y = 'def';

const fero = {
    name: name,
    lastName: lastName,
    
    foo: function () {
        return 'metóda foo';
    },
  
    // vytvorte property, ktorej názov je poskladaný z x a y.
};

console.log(fero.name);
console.log(fero.lastName);
console.log(fero.foo());
console.log(fero.abcdef);

V starom JS

Rozšírené objektové literály

const name = 'Ferko';
const lastName = 'Mrkvička';
const x = 'abc';
const y = 'def';

const fero = {
    name: name,
    lastName: lastName,
    
    foo: function () {
        return 'metóda foo';
    },
};

fero[x + y] =  'počítaná property';

console.log(fero.name);
console.log(fero.lastName);
console.log(fero.foo());
console.log(fero.abcdef);

V starom JS

Rozšírené objektové literály

const name = 'Ferko';
const lastName = 'Mrkvička';
const x = 'abc';
const y = 'def';

const fero = {
    name,
    lastName,
    
    foo() {
        return 'metóda foo';
    },
    
    [x + y]: 'počítaná property',
};

console.log(fero.name);
console.log(fero.lastName);
console.log(fero.foo());
console.log(fero.abcdef);

V novom JS

const name = 'Ferko';
const lastName = 'Mrkvička';
const x = 'abc';
const y = 'def';

const fero = {
    name,
    lastName,
    
    foo() {
        return 'metóda foo';
    },
    
    [x + y]: 'počítaná property',
};

console.log(fero.name);
console.log(fero.lastName);
console.log(fero.foo());
console.log(fero.abcdef);
const name = 'Ferko';
const lastName = 'Mrkvička';
const x = 'abc';
const y = 'def';

const fero = {
    name: name,
    lastName: lastName,
    
    foo: function () {
        return 'metóda foo';
    },
};

fero[x + y] =  'počítaná property';

console.log(fero.name);
console.log(fero.lastName);
console.log(fero.foo());
console.log(fero.abcdef);

Destructuring - polia

const [x, y] = [1, 2];

const pole = ['agát', 'blýskavica', 'cieľovníci'];

const [a, , c] = pole;

const [foo, bar, baz = 33] = [11, 22];

// výmena hodnôt dvoch prvkov

let [var1, var2] = ['value 1', 'value 2'];

[var2, var1] = [var1, var2];

Destructuring - objekty

const obj = {
    foo: 1,
    bar: 2,
    baz: 3,
};

const { foo, baz } = obj;

// prípadne pod iným názvom
const { foo: aliasFoo, baz } = obj;

// default hodnoty

const { foo, xyz = 42 } = obj;

Destructuring - objekty

// argumenty funkcie

const params = {
    logger: 'console',
    isDev:  true,
};

foo(params);

const foo = function ({ isDev, logger }) {
    console.log(logger);
    console.log(isDev);
};

Opakovanie

Algoritmus a algoritmizácia

Algoritmus je postup riešenia problému

Algoritmizácia je vytváranie tohto postupu

Najefektívnejším spôsobom algoritmizovania je postupné rozkladanie problému na menšie časti. Tzv. Divide & Conquer

Počítač neurobí to, čo chcem.

Urobí to, čo mu poviem.

Programovací jazyk

Vysoko formalizovaný jazyk so striktnými pravidlami, pomocou ktorého vieme zapísať algoritmus

Základné stavebné bloky programovacieho jazyka

  • dáta (premenné, konštanty)
  • funkcie

Premenné

Slúžia na ukladanie dát v pamäti počas behu programu

Deklarujeme pomocou kľúčových slov

  • var
  • let
  • const

Typy premenných

Primitívne

  • boolean
  • číslo
  • reťazec
  • null
  • undefined

Zložené

  • objekt
  • pole
  • funkcia

Funkcie

Slúžia na rozdeľovanie algoritmu na menšie časti

Je dôlezité ich trefne pomenovávať

function abc(param) {
    console.log(param);
}

const def = function (param) {
    console.log(param);
}

const ghi = (param) => {
    console.log(param);
}

Pokiaľ je funkcia súčasťou objektu, hovoríme jej metóda.

Podmienky

Slúžia na podmienené vykonávanie kódu

if (podmienka) {
    príkaz();
}

if (podmienka) {
    príkaz1();
} else if {
    príkaz2();
} else {
    príkaz3();
}

if (podmienka1 && podmienka2) {
    príkaz();
}

if (podmienka1 || podmienka2) {
    príkaz();
}

Cykly

Slúžia na opakované vykonávanie kódu

while (podmienka) {
    príkaz();
}

do {
    príkaz();
} while (podmienka);

for (let i = 0; i < 10; i += 1) {
    príkaz();
}

for (let vlastnost in objekt) {
    console.log(objekt[vlastnost]);
}

Operátory

Pomocou operátorov robíme operácie s dátami

  • priraďovacie (=, +=)
  • matematické (+, -, *, /, %, **)
  • logické (&&, ||)
  • na prácu s reťazcami (+)
  • ...

Tipy na štúdium

Základný nástroj pre akýkoľvek projekt

git

Chcem programovať krátke skripty pre ecom nástroje

Témy a nástroje:

Chcem programovať webstránky

Témy a nástroje:

Chcem programovať aplikácie pre mobily

  • React Native
  • testovanie
  • HTTP REST API a/alebo GraphQL
  • databázy (Firebase, SQLite, MariaDB/MySQL)

Témy a nástroje:

Chcem programovať aplikácie pre PC

Témy a nástroje:

  • všetko z tipov pre webstránky :)
  • a navyše Electron

Chcem programovať hry

Témy a nástroje:

  • podľa cieľového prostredia (web, mobil, PC)
  • navyše:
    • game engine
    • websockets
    • základy matematiky a fyziky (vektory, sila, rýchlosť)
    • návrhové vzory (Design Patterns)
    • základy hernej "umelej inteligencie"

Tipy na kurzy, videá, knihy a pod.

Kurzy a videá

Douglas Crockford

JavaScript: The Good Parts

  • ✅ veľmi dobrá pre získanie hlbšieho pochopenia JavaScriptu
  • ❌ nie úplne pre začiatočníkov
  • ❌ niektoré neaktuálne veci

Josh Goldberg

Learning Typescript

TypeScript je nadstavba JavaScript-u, ktorá mu dodáva striktnú typovosť.

Kde využiť získané znalosti mimo programovania?

Algoritmizácia

Metóda "rozdeľuj a panuj" vie pomôcť v riešení problémov a životných situácii všeobecne.

Lepšie porozumenie fungovaniu webstránok a softvéru všeobecne

Lepšie porozumenie práci programátorov

Lepšie porozumenie pozadiu pri práci s nocode nástrojmi (Power Automate, Apps, BI...)

Občasné skriptovanie

  • skripty pre GTM, ecom nástroje alebo malé pluginy pre WordPress a pod.
  • spracovávanie dát z Excelu
  • automatizovanie opakujúcich sa úloh

Tvorba modov do hier

Certifikát

Úloha: naprogramujte generátor certifikátov o ukončení školenia pre každého účastníka

  • certifikát bude obrázok v SVG formáte
  • SVG markup vygeneruje váš kód v JavaScript-e

Rýchlokurz SVG

<svg height="210mm" width="297mm" viewBox="0 0 2100 2970">
    <rect
        x="100"
        y="100"
        width="1900"
        height="2770"
        fill="green"
        stroke="black"
        stroke-width="10"
    />
  
    <text
        x="1486"
        y="1050"
        text-anchor="middle"
        font-size="35mm"
    >
        Základy programovania v JavaScripte
    </text>
  
    <line
        x1="1770"
        y1="1600"
        x2="2670"
        y2="1600"
        stroke="black"
        stroke-width="3"
    />
</svg>
// súbor certificate.js
function generateCertificate() {
    const height = 2100;
    const width = 2970;
    const centerX = width / 2;
    const centerY = height / 2;
    const quarterWidth = width / 4;

    return `
        <svg height="210mm" width="297mm" viewBox="0 0 ${width} ${height}" xmlns="http://www.w3.org/2000/svg"
        >
            <rect x="50" y="50" width="2870" height="2000" stroke="black" fill="none" stroke-width="1" rx="15" />
            <text x="${centerX}" y="250" class="title" text-anchor="middle">Potvrdenie o absolvovaní kurzu</text>
            <text x="${centerX}" y="550" text-anchor="middle" class="name">Ferko Mrkvička</text>
            <text x="${centerX}" y="750" text-anchor="middle" class="normal">úspešne absolvoval kurz</text>
            <text x="${centerX}" y="${centerY}" class="course-title" text-anchor="middle">Základy programovania v JavaScripte</text>
            <rect x="1770" y="1450" width="900" height="150" fill="white" class="signature-box"/>
            <line x1="1770" y1="1600" x2="2670" y2="1600" stroke="black" stroke-width="3" />
            <text x="${
                quarterWidth * 3
            }" y="1680" text-anchor="middle" class="normal">Lektor: Milan Herda</text>
            <text x="${
                quarterWidth * 3
            }" y="1750" text-anchor="middle" class="small">Dátum: 21.2.2023</text>
            <text x="450" y="1500" text-anchor="start" class="normal">Dĺžka kurzu: 45 hodín</text>
            <text x="450" y="1600" text-anchor="start" class="normal">Forma: prezenčná</text>
            <text x="150" y="1950" text-anchor="start" class="footer">https://www.programatorske-skolenia.sk/</text>
            <text x="2820" y="1950" text-anchor="end" class="footer">https://www.perunhq.org/</text>
        </svg>
    `;
}

document.querySelector('#app').innerHTML = generateCertificate();

Stiahnite si túto funkciu pre generovanie certifikátu

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>Certifikát</title>
        <style>
        svg {
            border: solid 1px black;
        }

        .title {
            font-size: 25mm;
            font-weight: bold;
        }

        .course-title {
            font-size: 35mm;
            font-weight: bold;
        }

        .name {
            font-size: 30mm;
            font-weight: bold;
        }

        .normal {
            font-size: 15mm;
        }

        .small {
            font-size: 12mm;
        }

        .footer {
            font-size: 8mm;
            fill: grey;
        }

        .signature-box: {
            border-bottom: solid 1px black;
        }

        </style>
    </head>
    <body>
        <div id="app"></div>
        <script src="./certificate.js"></script>
     </body>
</html>

Môže byť použitá napríklad v takomto HTML súbore

Úloha: Upravte funkciu tak, aby:

  • meno absolventa prišlo ako parameter
  • text "úspešne absolvoval" sa skloňoval podľa pohlavia
    • áno, znamená to, že aj pohlavie musí prísť ako parameter
const GENDER_MALE = 'male';
const GENDER_FEMALE = 'female';

function generateCertificate(name, gender) {
    // ...
  
    let completedText = 'úspešne absolvovala kurz';

    if (gender === GENDER_MALE) {
        completedText = 'úspešne absolvoval kurz';
    }

    return `
        <svg height="210mm" width="297mm" ... >
            <rect ... />
            <text ...>Potvrdenie o absolvovaní kurzu</text>
            <text ...>${name}</text>
            <text ...>${completedText}</text>
            <text ...>Základy programovania v JavaScripte</text>
            <!-- ... -->
        </svg>
    `;
}

Riešenie:

Úloha: Vytvorte funkciu generateCertificates, ktorá:

  • dostane zoznam absolventov ako argument
  • každý študent bude reprezentovaný ako objekt s vlastnosťami name a gender
  • funkcia vygeneruje SVG obrázok certifikátu pre každého absolventa
const students = [
    {
        name: 'Ferko Mrkvička',
        gender: GENDER_MALE,
    },
    {
        name: 'Janka Nová',
        gender: GENDER_FEMALE,
    },
];

function generateCertificates(students) {
    let certificatesHtml = '';

    for (let i = 0; i < students.length; i += 1) {
        certificatesHtml =
            certificatesHtml + generateCertificate(students[i].name, students[i].gender);
    }

    return certificatesHtml;
}

function generateCertificate(name, gender) {
    // ...
}

document.querySelector('#app').innerHTML = generateCertificates(students);

Riešenie:

Nie sú certifikáty zvyčajne viac...

fancy,

s farbami,

vlnovkami a tak?

Zložitejšie tvary v SVG

<path
    d="
       M 200, 150
       l 400, 750
       l -400, 0
       Z
    "
    fill="red"
    stroke="black"
    stroke-width="1"
/>

Zložitejšie tvary v SVG

<path
    d="
       M 500, 400
       q 200, -350, 400, 0
       Z
    "
    fill="blue"
    stroke="black"
    stroke-width="10"
/>

Zložitejšie tvary v SVG

<path
    d="
       M 500, 400
       q 200, -350, 400, 0
       Z
    "
    fill="blue"
    stroke="black"
    stroke-width="10"
/>
<path
    d="
       M 1000, 400
       q 200, -350, 400, 0
       Z
    "
    fill="none"
    stroke="black"
    stroke-width="10"
/>

Zložitejšie tvary v SVG

<path
    d="
       M 500, 400
       q 200, -350, 400, 0
       Z
    "
    fill="blue"
    stroke="black"
    stroke-width="10"
/>
<path
    d="
       M 1000, 400
       q 200, -350, 400, 0
       Z
    "
    fill="none"
    stroke="black"
    stroke-width="10"
/>
<path
    d="
       M 1500, 400
       q 200, -350, 400, 0
    "
    fill="none"
    stroke="black"
    stroke-width="10"
/>

Zložitejšie tvary v SVG

<path
    d="
       M 1500, 400
       q 200, -350, 400, 0
       t 400, 0,
         400, 0,
         400, 0
    "
    fill="none"
    stroke="black"
    stroke-width="10"
/>

Urobme si funkciu na generovanie príkazov pre vlnovku

function getRelativeWaveCommand(controlPoint, stepPoint, numOfWaves) {
    if (numOfWaves < 1) {
        return '';
    }

    let command = `q ${controlPoint.x}, ${controlPoint.y}, ${stepPoint.x}, ${stepPoint.y}`;

    if (numOfWaves > 1) {
        command = command + ' t ';
    }

    for (let i = 0; i < numOfWaves - 1; i += 1) {
        command = command + `${stepPoint.x}, ${stepPoint.y} `;
    }

    return command;
}

Skúsme vygenerovať vlnovku na pozadie

function generateBackground() {
    return `
        <path
             d="
                 M 0, 2
                 ${getRelativeWaveCommand(
                     { x: 4, y -4},
                     { x: 6, y: 0},
                     10
                 )} 
             "
             fill="none"
             stroke="red"
             stroke-width="1"
        />
    `;
}

function generateCertificate(name, gender) {
    // ...
    return `
        <svg ...>
            ${generateBackground()}
            // ...
        </svg>
    `; 
}

Skúsme vygenerovať vlnovku na pozadie na celú šírku

function generateBackground() {
    return `
        <path
             d="
                 M 0, 2
                 ${getRelativeWaveCommand(
                     { x: 4, y -4},
                     { x: 6, y: 0},
                     2970 / 6
                 )} 
             "
             fill="none"
             stroke="red"
             stroke-width="1"
        />
    `;
}

function generateCertificate(name, gender) {
    // ...
    return `
        <svg ...>
            ${generateBackground()}
            // ...
        </svg>
    `; 
}

Skúsme ju zopakovať pre celú výšku (opakujme po 6 bodoch)

function generateBackground() {
    let paths = '';

    for (let i = 0; i < 2100 / 6; i += 1) {
        paths += `<path d="M 0,${2 + i * 6} ${getRelativeWaveCommand(
            { x: 4, y: -4 },
            { x: 6, y: 0 },
            2970 / 6
        )}" fill="none" stroke="red" stroke-width="1" />`;
    }

    return paths;
}

function generateCertificate(name, gender) {
    // ...
    return `
        <svg ...>
            ${generateBackground()}
            // ...
        </svg>
    `; 
}

Nemajú certifikáty prelínajúce sa vlnovky rôznych farieb?

Pridajme modrú vlnovku kúsok za červenou

function generateBackground() {
    let paths = '';

    for (let i = 0; i < 2100 / 6; i += 1) {
        paths += `<path d="M 0,${2 + i * 6} ${getRelativeWaveCommand(
            { x: 4, y: -4 },
            { x: 6, y: 0 },
            2970 / 6
        )}" fill="none" stroke="red" stroke-width="1" />`;

        paths += `<path d="M 0,${4 + i * 6} ${getRelativeWaveCommand(
            { x: 4, y: 4 },
            { x: 6, y: 0 },
            2970 / 6
        )}" fill="none" stroke="blue" stroke-width="1" />`;

    }

    return paths;
}

Nedalo by sa urobiť vlnovkové orámovanie pre štvorec?

function generateWavyRect() {
    const wavesOnWidth = (2770 - (15 - 5) * 2) / 30 - 1;
    const wavesOnHeight = (1900 - (15 - 5) * 2) / 30 - 1;

    const waveOnTop = getRelativeWaveCommand({ x: 15, y: 10 }, { x: 30, y: 0 }, wavesOnWidth);
    const waveOnRight = getRelativeWaveCommand({ x: -10, y: 15 }, { x: 0, y: 30 }, wavesOnHeight);
    const waveOnBottom = getRelativeWaveCommand({ x: -15, y: -10 }, { x: -30, y: 0 }, wavesOnWidth);
    const waveOnLeft = getRelativeWaveCommand({ x: 10, y: -15 }, { x: 0, y: -30 }, wavesOnHeight);

    return `
        <path d="
                M 100,115
                a 15,15,0,0,1,15,-15
                l 5,0
                ${waveOnTop}
                l 5,0
                a 15,15,0,0,1,15,15
                l 0,5
                ${waveOnRight}
                l 0,5
                a 15,15,0,0,1,-15,15
                l -5,0
                ${waveOnBottom}
                l -5,0
                a 15,15,0,0,1,-15,-15
                l 0,-5
                ${waveOnLeft}
                l 0,-5
                Z
            " fill="rgba(255, 255, 255, 0.5)" stroke="black" stroke-width="1"
        />
    `;
}

Vlnovkové orámovanie pre štvorec:

function generateCertificate(name, gender) {
    // ...
    return `
        <svg ...>
            ${generateBackground()}
            <rect ... />
            ${generateWavyRect()}
            // ...
        </svg>
    `; 
}

Vlnovkové orámovanie pre štvorec:

Certifikáty viete z JavaScriptu poslať aj na tlačiareň

window.print();

A to je všetko

Školenie JS 2020 - záver

By Milan Herda

Školenie JS 2020 - záver

  • 294