diff --git a/1-js/01-getting-started/1-intro/article.md b/1-js/01-getting-started/1-intro/article.md index 9395c9fe1..8bbde5708 100644 --- a/1-js/01-getting-started/1-intro/article.md +++ b/1-js/01-getting-started/1-intro/article.md @@ -18,11 +18,11 @@ Když byl JavaScript vytvořen, jmenoval se původně jinak: „LiveScript“. A Postupně při vývoji se však JavaScript stal zcela nezávislým jazykem se svou vlastní specifikací nazvanou [ECMAScript](http://cs.wikipedia.org/wiki/ECMAScript) a nyní nemá k Javě vůbec žádný vztah. ``` -Dnes je možné spouštět JavaScript nejen v prohlížeči, ale i na serveru nebo na kterémkoli zařízení, které obsahuje zvláštní program nazvaný [JavaScriptový engine](https://en.wikipedia.org/wiki/JavaScript_engine). +Dnes je možné spouštět JavaScript nejen v prohlížeči, ale i na serveru nebo na kterémkoli zařízení, které obsahuje zvláštní program nazvaný [JavaScriptový motor](https://en.wikipedia.org/wiki/JavaScript_engine). -Prohlížeč má zabudovaný engine, který se někdy nazývá „virtuální stroj JavaScriptu“. +Prohlížeč má zabudovaný motor (anglicky *engine*), který se někdy nazývá „virtuální stroj JavaScriptu“. -Různé enginy mají různá „kódová označení“. Například: +Různé motory mají různá „kódová označení“. Například: - [V8](https://en.wikipedia.org/wiki/V8_(JavaScript_engine)) -- v Chrome, Opeře a Edge. - [SpiderMonkey](https://cs.wikipedia.org/wiki/SpiderMonkey) -- ve Firefoxu. @@ -30,15 +30,15 @@ Různé enginy mají různá „kódová označení“. Například: Výše uvedené pojmy je dobré si pamatovat, protože se používají ve vývojářských článcích na internetu. Budeme je používat i my. Například je-li uvedeno „vlastnost X je podporována ve V8“, znamená to, že pravděpodobně bude fungovat v Chrome, Opeře a Edge. -```smart header="Jak enginy fungují?" +```smart header="Jak motory fungují?" -Enginy jsou složité, ale jejich základy jsou jednoduché. +Motory jsou složité, ale jejich základy jsou jednoduché. -1. Engine (v případě prohlížeče zahrnutý do něj) načte („rozebere“, „parsuje“) skript. +1. Motor (v případě prohlížeče zahrnutý do něj) načte („rozebere“, „parsuje“) skript. 2. Pak přeloží („zkompiluje“) skript do strojového kódu. 3. A pak se strojový kód hezky rychle spustí. -Při každém kroku procesu engine aplikuje optimalizace. Dokonce sleduje, jak zkompilovaný skript běží, analyzuje data, která jím protékají, a podle těchto znalostí dále optimalizuje strojový kód. +Při každém kroku procesu motor aplikuje optimalizace. Dokonce sleduje, jak zkompilovaný skript běží, analyzuje data, která jím protékají, a podle těchto znalostí dále optimalizuje strojový kód. ``` ## Co může JavaScript v prohlížeči dělat? @@ -109,7 +109,7 @@ Příklady takových jazyků: - [CoffeeScript](https://coffeescript.org/) je „syntaktický cukr“ pro JavaScript, který zavádí kratší syntaxi a tím nám umožňuje psát čistší a přesnější kód. Obvykle jej mají v oblibě vývojáři, kteří používají jazyk Ruby. - [TypeScript](https://www.typescriptlang.org/) se soustředí na přidání „striktního, silně typovaného systému“, aby zjednodušil vývoj a podporu složitých systémů. Vyvinula jej firma Microsoft. - [Flow](https://flow.org/) rovněž přidává typovací systém, ale jiným způsobem. Vyvinul jej Facebook. -- [Dart](https://www.dartlang.org/) je samostatný jazyk se svým vlastním enginem, který běží v prostředích mimo prohlížeč (např. v mobilních aplikacích), ale i ten může být transpilován do JavaScriptu. Vyvinut firmou Google. +- [Dart](https://www.dartlang.org/) je samostatný jazyk se svým vlastním motorem, který běží v prostředích mimo prohlížeč (např. v mobilních aplikacích), ale i ten může být transpilován do JavaScriptu. Vyvinut firmou Google. - [Brython](https://brython.info/) je transpiler Pythonu do JavaScriptu, který umožňuje psát aplikace v čistém Pythonu bez JavaScriptu. - [Kotlin](https://kotlinlang.org/docs/reference/js-overview.html) je moderní, stručný a bezpečný programovací jazyk, jehož cílem může být prohlížeč nebo Node. diff --git a/1-js/01-getting-started/4-devtools/article.md b/1-js/01-getting-started/4-devtools/article.md index 02da6b4df..d5cc32e17 100644 --- a/1-js/01-getting-started/4-devtools/article.md +++ b/1-js/01-getting-started/4-devtools/article.md @@ -22,7 +22,7 @@ Otevřou se vývojářské nástroje na záložce „Console“. Budou vypadat zhruba takto: -![chrome](chrome.png) +![chrome](chrome.webp) Vzhled vývojářských nástrojů závisí na vaší verzi Chrome. Čas od času se mění, ale měl by se podobat obrázku. @@ -49,8 +49,8 @@ Jejich vzhled je vcelku podobný. Až budete vědět, jak používat nástroje v Safari (prohlížeč pro Mac, není podporován ve Windows nebo Linuxu) je v tomto ohledu trochu zvláštní. Nejprve musíme povolit „menu Vývoj“. -Otevřete „Preferences“ a jděte na záložku „Advanced“. Dole uvidíte checkbox, který zaškrtněte: - +Otevřete „Settings“ a jděte na záložku „Advanced“. Dole uvidíte checkbox, který zaškrtněte: + ![safari](safari.png) Nyní můžete zapínat konzoli pomocí `key:Cmd+Opt+C`. Všimněte si také, že v horním menu se objevila nová položka s názvem „Develop“ („Vývoj“), která obsahuje mnoho příkazů a nastavení. diff --git a/1-js/01-getting-started/4-devtools/chrome.png b/1-js/01-getting-started/4-devtools/chrome.png deleted file mode 100644 index 4cb3ea2f4..000000000 Binary files a/1-js/01-getting-started/4-devtools/chrome.png and /dev/null differ diff --git a/1-js/01-getting-started/4-devtools/chrome.webp b/1-js/01-getting-started/4-devtools/chrome.webp new file mode 100644 index 000000000..bdf067079 Binary files /dev/null and b/1-js/01-getting-started/4-devtools/chrome.webp differ diff --git a/1-js/01-getting-started/4-devtools/chrome@2.webp b/1-js/01-getting-started/4-devtools/chrome@2.webp new file mode 100644 index 000000000..2aeca5898 Binary files /dev/null and b/1-js/01-getting-started/4-devtools/chrome@2.webp differ diff --git a/1-js/01-getting-started/4-devtools/chrome@2x.png b/1-js/01-getting-started/4-devtools/chrome@2x.png deleted file mode 100644 index b87404a8f..000000000 Binary files a/1-js/01-getting-started/4-devtools/chrome@2x.png and /dev/null differ diff --git a/1-js/01-getting-started/4-devtools/safari.png b/1-js/01-getting-started/4-devtools/safari.png index 64c7a3f6c..4538827eb 100644 Binary files a/1-js/01-getting-started/4-devtools/safari.png and b/1-js/01-getting-started/4-devtools/safari.png differ diff --git a/1-js/01-getting-started/4-devtools/safari@2x.png b/1-js/01-getting-started/4-devtools/safari@2x.png index 27def4d09..1561b2bd9 100644 Binary files a/1-js/01-getting-started/4-devtools/safari@2x.png and b/1-js/01-getting-started/4-devtools/safari@2x.png differ diff --git a/1-js/02-first-steps/10-ifelse/2-check-standard/ifelse_task2.svg b/1-js/02-first-steps/10-ifelse/2-check-standard/ifelse_task2.svg index 050264a37..f2eca800a 100644 --- a/1-js/02-first-steps/10-ifelse/2-check-standard/ifelse_task2.svg +++ b/1-js/02-first-steps/10-ifelse/2-check-standard/ifelse_task2.svg @@ -1 +1 @@ -ZačátekVy to nevíte? “ECMAScript”!Správně!Jaký je "oficiální" název JavaScriptu?JinéECMAScript \ No newline at end of file +ZačátekVy to nevíte? “ECMAScript”!Správně!Jaký je "oficiální" název JavaScriptu?JinéECMAScript \ No newline at end of file diff --git a/1-js/02-first-steps/16-function-expressions/article.md b/1-js/02-first-steps/16-function-expressions/article.md index e012091b9..98ffee136 100644 --- a/1-js/02-first-steps/16-function-expressions/article.md +++ b/1-js/02-first-steps/16-function-expressions/article.md @@ -82,11 +82,7 @@ let řekniAhoj = function() { // (1) vytvoření alert( "Ahoj" ); }; -<<<<<<< HEAD -let funkce = řekniAhoj; -======= -let func = sayHi; //(2) ->>>>>>> 1dce5b72b16288dad31b7b3febed4f38b7a5cd8a +let funkce = řekniAhoj; // (2) // ... ``` diff --git a/1-js/03-code-quality/01-debugging-chrome/chrome-sources-breakpoint.svg b/1-js/03-code-quality/01-debugging-chrome/chrome-sources-breakpoint.svg index 9cccdfb03..71cd45bc1 100644 --- a/1-js/03-code-quality/01-debugging-chrome/chrome-sources-breakpoint.svg +++ b/1-js/03-code-quality/01-debugging-chrome/chrome-sources-breakpoint.svg @@ -1 +1 @@ -zde je seznamzarážky \ No newline at end of file +zde je seznamzarážky \ No newline at end of file diff --git a/1-js/03-code-quality/01-debugging-chrome/chrome-sources-debugger-pause.svg b/1-js/03-code-quality/01-debugging-chrome/chrome-sources-debugger-pause.svg index 6835bfaa4..b5fc0b33d 100644 --- a/1-js/03-code-quality/01-debugging-chrome/chrome-sources-debugger-pause.svg +++ b/1-js/03-code-quality/01-debugging-chrome/chrome-sources-debugger-pause.svg @@ -1 +1 @@ -213viz detaily vnějšího volánísledování výrazůaktuální proměnné \ No newline at end of file +213viz detaily vnějšího volánísledování výrazůaktuální proměnné \ No newline at end of file diff --git a/1-js/03-code-quality/01-debugging-chrome/chrome-sources-debugger-trace-1.svg b/1-js/03-code-quality/01-debugging-chrome/chrome-sources-debugger-trace-1.svg index cea51b5b5..be27a8106 100644 --- a/1-js/03-code-quality/01-debugging-chrome/chrome-sources-debugger-trace-1.svg +++ b/1-js/03-code-quality/01-debugging-chrome/chrome-sources-debugger-trace-1.svg @@ -1 +1 @@ -vnořená volání \ No newline at end of file +vnořená volání \ No newline at end of file diff --git a/1-js/03-code-quality/05-testing-mocha/beforeafter.view/test.js b/1-js/03-code-quality/05-testing-mocha/beforeafter.view/test.js index d3de82546..a1dcd5bcc 100644 --- a/1-js/03-code-quality/05-testing-mocha/beforeafter.view/test.js +++ b/1-js/03-code-quality/05-testing-mocha/beforeafter.view/test.js @@ -1,16 +1,16 @@ describe("test", function() { - // Mocha usually waits for the tests for 2 seconds before considering them wrong + // Mocha obvykle čeká na provedení testu 2 sekundy a pak jej považuje za špatný - this.timeout(200000); // With this code we increase this - in this case to 200,000 milliseconds + this.timeout(200000); // S tímto kódem to můžeme zvýšit - v tomto případě na 200 000 milisekund - // This is because of the "alert" function, because if you delay pressing the "OK" button the tests will not pass! + // To je kvůli funkci "alert", protože jestliže budete zaváhat se stisknutím tlačítka "OK", testy neprojdou! - before(() => alert("Testing started – before all tests")); - after(() => alert("Testing finished – after all tests")); + before(() => alert("Začíná testování - před všemi testy")); + after(() => alert("Končí testování - po všech testech")); - beforeEach(() => alert("Before a test – enter a test")); - afterEach(() => alert("After a test – exit a test")); + beforeEach(() => alert("Před testem - vstup do testu")); + afterEach(() => alert("Po testu - výstup z testu")); it('test 1', () => alert(1)); it('test 2', () => alert(2)); diff --git a/1-js/03-code-quality/05-testing-mocha/pow-1.view/test.js b/1-js/03-code-quality/05-testing-mocha/pow-1.view/test.js index 89ba412ed..0b6ad7fbd 100644 --- a/1-js/03-code-quality/05-testing-mocha/pow-1.view/test.js +++ b/1-js/03-code-quality/05-testing-mocha/pow-1.view/test.js @@ -1,7 +1,7 @@ -describe("pow", function() { +describe("mocnina", function() { - it("raises to n-th power", function() { - assert.equal(pow(2, 3), 8); + it("umocňuje na n-tou", function() { + assert.equal(mocnina(2, 3), 8); }); }); diff --git a/1-js/03-code-quality/05-testing-mocha/pow-2.view/test.js b/1-js/03-code-quality/05-testing-mocha/pow-2.view/test.js index c803f0e61..dfda8a632 100644 --- a/1-js/03-code-quality/05-testing-mocha/pow-2.view/test.js +++ b/1-js/03-code-quality/05-testing-mocha/pow-2.view/test.js @@ -1,11 +1,11 @@ -describe("pow", function() { +describe("mocnina", function() { - it("2 raised to power 3 is 8", function() { - assert.equal(pow(2, 3), 8); + it("2 na 3 je 8", function() { + assert.equal(mocnina(2, 3), 8); }); - it("3 raised to power 4 is 81", function() { - assert.equal(pow(3, 4), 81); + it("3 na 4 je 81", function() { + assert.equal(mocnina(3, 4), 81); }); }); diff --git a/1-js/03-code-quality/05-testing-mocha/pow-3.view/test.js b/1-js/03-code-quality/05-testing-mocha/pow-3.view/test.js index 8663952aa..268daeaf2 100644 --- a/1-js/03-code-quality/05-testing-mocha/pow-3.view/test.js +++ b/1-js/03-code-quality/05-testing-mocha/pow-3.view/test.js @@ -1,14 +1,14 @@ -describe("pow", function() { +describe("mocnina", function() { - function makeTest(x) { - let expected = x * x * x; - it(`${x} in the power 3 is ${expected}`, function() { - assert.equal(pow(x, 3), expected); + function vytvořTest(x) { + let očekáváno = x * x * x; + it(`${x} na 3 je ${očekáváno}`, function() { + assert.equal(mocnina(x, 3), očekáváno); }); } for (let x = 1; x <= 5; x++) { - makeTest(x); + vytvořTest(x); } }); diff --git a/1-js/03-code-quality/05-testing-mocha/pow-4.view/test.js b/1-js/03-code-quality/05-testing-mocha/pow-4.view/test.js index e5ce2ce43..99ff33cf8 100644 --- a/1-js/03-code-quality/05-testing-mocha/pow-4.view/test.js +++ b/1-js/03-code-quality/05-testing-mocha/pow-4.view/test.js @@ -1,19 +1,17 @@ -describe("pow", function() { +describe("mocnina", function() { - describe("raises x to power 3", function() { + describe("umocní x na 3", function() { - function makeTest(x) { - let expected = x * x * x; - it(`${x} in the power 3 is ${expected}`, function() { - assert.equal(pow(x, 3), expected); + function vytvořTest(x) { + let očekáváno = x * x * x; + it(`${x} na 3 je ${očekáváno}`, function() { + assert.equal(mocnina(x, 3), očekáváno); }); } for (let x = 1; x <= 5; x++) { - makeTest(x); + vytvořTest(x); } }); - - // ... more tests to follow here, both describe and it can be added }); diff --git a/1-js/03-code-quality/05-testing-mocha/pow-full.view/test.js b/1-js/03-code-quality/05-testing-mocha/pow-full.view/test.js index 75ff5e99f..881d8bb5b 100644 --- a/1-js/03-code-quality/05-testing-mocha/pow-full.view/test.js +++ b/1-js/03-code-quality/05-testing-mocha/pow-full.view/test.js @@ -1,26 +1,26 @@ -describe("pow", function() { +describe("mocnina", function() { - describe("raises x to power 3", function() { + describe("umocní x na 3", function() { - function makeTest(x) { - let expected = x * x * x; - it(`${x} in the power 3 is ${expected}`, function() { - assert.equal(pow(x, 3), expected); + function vytvořTest(x) { + let očekáváno = x * x * x; + it(`${x} na 3 je ${očekáváno}`, function() { + assert.equal(mocnina(x, 3), očekáváno); }); } for (let x = 1; x <= 5; x++) { - makeTest(x); + vytvořTest(x); } }); - it("if n is negative, the result is NaN", function() { - assert.isNaN(pow(2, -1)); + it("je-li n záporné, výsledek je NaN", function() { + assert.isNaN(mocnina(2, -1)); }); - it("if n is not integer, the result is NaN", function() { - assert.isNaN(pow(2, 1.5)); + it("je-li n necelé, výsledek je NaN", function() { + assert.isNaN(mocnina(2, 1.5)); }); }); diff --git a/1-js/03-code-quality/05-testing-mocha/pow-min.view/test.js b/1-js/03-code-quality/05-testing-mocha/pow-min.view/test.js index 89ba412ed..981bbaac2 100644 --- a/1-js/03-code-quality/05-testing-mocha/pow-min.view/test.js +++ b/1-js/03-code-quality/05-testing-mocha/pow-min.view/test.js @@ -1,7 +1,7 @@ -describe("pow", function() { +describe("mocnina", function() { - it("raises to n-th power", function() { - assert.equal(pow(2, 3), 8); + it("umocní na n-tou", function() { + assert.equal(mocnina(2, 3), 8); }); }); diff --git a/1-js/03-code-quality/05-testing-mocha/pow-nan.view/test.js b/1-js/03-code-quality/05-testing-mocha/pow-nan.view/test.js index 75ff5e99f..88e218c49 100644 --- a/1-js/03-code-quality/05-testing-mocha/pow-nan.view/test.js +++ b/1-js/03-code-quality/05-testing-mocha/pow-nan.view/test.js @@ -1,26 +1,26 @@ -describe("pow", function() { +describe("mocnina", function() { - describe("raises x to power 3", function() { + describe("umocní x na 3", function() { - function makeTest(x) { - let expected = x * x * x; - it(`${x} in the power 3 is ${expected}`, function() { - assert.equal(pow(x, 3), expected); + function vytvořTest(x) { + let očekáváno = x * x * x; + it(`${x} na 3 je ${očekáváno}`, function() { + assert.equal(mocnina(x, 3), očekáváno); }); } for (let x = 1; x <= 5; x++) { - makeTest(x); + vytvořTest(x); } }); - it("if n is negative, the result is NaN", function() { - assert.isNaN(pow(2, -1)); + it("pro záporné n je výsledek NaN", function() { + assert.isNaN(mocnina(2, -1)); }); - it("if n is not integer, the result is NaN", function() { - assert.isNaN(pow(2, 1.5)); + it("pro necelé n je výsledek NaN", function() { + assert.isNaN(mocnina(2, 1.5)); }); }); diff --git a/1-js/03-code-quality/06-polyfills/article.md b/1-js/03-code-quality/06-polyfills/article.md index f8e0b5c59..2156ce307 100644 --- a/1-js/03-code-quality/06-polyfills/article.md +++ b/1-js/03-code-quality/06-polyfills/article.md @@ -1,4 +1,3 @@ - # Polyfilly a transpilátory Jazyk JavaScript se neustále vyvíjí. Pravidelně se pro tento jazyk objevují nové návrhy, ty jsou analyzovány a jsou-li shledány užitečnými, přidají se na seznam na a pak pokračují do [specifikace](https://www.ecma-international.org/publications-and-standards/standards/ecma-262/). @@ -86,4 +85,4 @@ Dobré zdroje, které ukazují aktuální stav podpory různých vlastností: - - pro funkce vztahující se k prohlížeči. -P.S. Pokud se týká vlastností jazyka, obvykle je nejaktuálnější Google Chrome. Pokud vám některé demo v tomto tutoriálu selže, zkuste ho. Většina dem v tutoriálu však funguje na kterémkoli moderním prohlížeči. +P.S. Pokud se týká vlastností jazyka, obvykle je nejaktuálnější Google Chrome. Pokud vám některé demo v tomto tutoriálu selže, zkuste ho. Většina dem v tutoriálu však funguje na kterémkoli moderním prohlížeči. \ No newline at end of file diff --git a/1-js/05-data-types/01-primitives-methods/article.md b/1-js/05-data-types/01-primitives-methods/article.md index 0965701be..23a0bcf89 100644 --- a/1-js/05-data-types/01-primitives-methods/article.md +++ b/1-js/05-data-types/01-primitives-methods/article.md @@ -6,7 +6,7 @@ Podíváme se na klíčové rozdíly mezi primitivy a objekty. Primitiv: -- Je hodnota primitivního typu. +- Představuje hodnotu primitivního typu. - Existuje 7 primitivních typů: `string`, `number`, `bigint`, `boolean`, `symbol`, `null` a `undefined`. Objekt: diff --git a/1-js/05-data-types/04-array/article.md b/1-js/05-data-types/04-array/article.md index 216112a2f..4212e5454 100644 --- a/1-js/05-data-types/04-array/article.md +++ b/1-js/05-data-types/04-array/article.md @@ -548,4 +548,4 @@ Pro porovnávání polí nepoužívejte operátor `==` (stejně jako `>`, `<` a Místo toho můžete použít cyklus `for..of` a porovnávat pole prvek po prvku. -V další kapitole budeme s poli pokračovat a prostudujeme další metody, jak přidávat, odstraňovat a vybírat prvky a jak pole řadit. \ No newline at end of file +V další kapitole budeme s poli pokračovat a prostudujeme další metody, jak přidávat, odstraňovat a vybírat prvky a jak pole řadit. diff --git a/1-js/05-data-types/05-array-methods/reduce.svg b/1-js/05-data-types/05-array-methods/reduce.svg index 180941dc2..7e8ce79cd 100644 --- a/1-js/05-data-types/05-array-methods/reduce.svg +++ b/1-js/05-data-types/05-array-methods/reduce.svg @@ -1 +1 @@ -1sum 0 current 12sum 0+1 current 23sum 0+1+2 current 34sum 0+1+2+3 current 45sum 0+1+2+3+4 current 50+1+2+3+4+5 = 15 \ No newline at end of file +1součet 0 aktuální 12součet 0+1 aktuální 23součet 0+1+2 aktuální 34součet 0+1+2+3 aktuální 45součet 0+1+2+3+4 aktuální 50+1+2+3+4+5 = 15 \ No newline at end of file diff --git a/1-js/05-data-types/10-destructuring-assignment/1-destruct-user/solution.md b/1-js/05-data-types/10-destructuring-assignment/1-destruct-user/solution.md index abf884c7c..091254563 100644 --- a/1-js/05-data-types/10-destructuring-assignment/1-destruct-user/solution.md +++ b/1-js/05-data-types/10-destructuring-assignment/1-destruct-user/solution.md @@ -5,9 +5,9 @@ let uživatel = { roky: 30 }; -let {jméno, roky: věk, jeAdmin = false} = uživatel; +let {jméno, roky: věk, jeSprávce = false} = uživatel; alert( jméno ); // Jan alert( věk ); // 30 -alert( jeAdmin ); // false +alert( jeSprávce ); // false ``` \ No newline at end of file diff --git a/1-js/05-data-types/10-destructuring-assignment/1-destruct-user/task.md b/1-js/05-data-types/10-destructuring-assignment/1-destruct-user/task.md index 748f31eda..45fd7ce3a 100644 --- a/1-js/05-data-types/10-destructuring-assignment/1-destruct-user/task.md +++ b/1-js/05-data-types/10-destructuring-assignment/1-destruct-user/task.md @@ -17,7 +17,7 @@ Napište destrukturační přiřazení, které načte: - vlastnost `jméno` do proměnné `jméno`. - vlastnost `roky` do proměnné `věk`. -- vlastnost `jeAdmin` do proměnné `jeAdmin` (false, pokud taková vlastnost není). +- vlastnost `jeSprávce` do proměnné `jeSprávce` (false, pokud taková vlastnost není). Zde je příklad hodnot po vašem přiřazení: @@ -29,5 +29,5 @@ let uživatel = { jméno: "Jan", roky: 30 }; alert( jméno ); // Jan alert( věk ); // 30 -alert( jeAdmin ); // false +alert( jeSprávce ); // false ``` diff --git a/1-js/05-data-types/10-destructuring-assignment/article.md b/1-js/05-data-types/10-destructuring-assignment/article.md index 28440bb3c..486755ccc 100644 --- a/1-js/05-data-types/10-destructuring-assignment/article.md +++ b/1-js/05-data-types/10-destructuring-assignment/article.md @@ -134,14 +134,14 @@ Existuje dobře známý trik pro výměnu hodnot dvou proměnných použitím de ```js run let host = "Jana"; -let admin = "Petr"; +let správce = "Petr"; -// Vyměníme hodnoty: učiníme host=Petr, admin=Jana +// Vyměníme hodnoty: učiníme host=Petr, správce=Jana *!* -[host, admin] = [admin, host]; +[host, správce] = [správce, host]; */!* -alert(`${host} ${admin}`); // Petr Jana (úspěšně vyměněno!) +alert(`${host} ${správce}`); // Petr Jana (úspěšně vyměněno!) ``` Zde jsme vytvořili dočasné pole dvou proměnných a okamžitě je destrukturovali v obráceném pořadí. diff --git a/1-js/05-data-types/12-json/article.md b/1-js/05-data-types/12-json/article.md index 891fcb050..535814f1b 100644 --- a/1-js/05-data-types/12-json/article.md +++ b/1-js/05-data-types/12-json/article.md @@ -39,7 +39,7 @@ Například zde zavoláme `JSON.stringify` na studenta: let student = { jméno: 'Jan', věk: 30, - jeAdmin: false, + jeSprávce: false, kurzy: ['html', 'css', 'js'], choť: null }; @@ -56,7 +56,7 @@ alert(json); { "jméno": "Jan", "věk": 30, - "jeAdmin": false, + "jeSprávce": false, "kurzy": ["html", "css", "js"], "choť": null } @@ -299,7 +299,7 @@ let uživatel = { jméno: "Jan", věk: 25, role: { - jeAdmin: false, + jeSprávce: false, jeEditor: true } }; @@ -310,7 +310,7 @@ alert(JSON.stringify(uživatel, null, 2)); "jméno": "Jan", "věk": 25, "role": { - "jeAdmin": false, + "jeSprávce": false, "jeEditor": true } } @@ -321,7 +321,7 @@ alert(JSON.stringify(uživatel, null, 2)); "jméno": "Jan", "věk": 25, "role": { - "jeAdmin": false, + "jeSprávce": false, "jeEditor": true } } @@ -427,7 +427,7 @@ alert( čísla[1] ); // 1 Nebo pro vnořené objekty: ```js run -let dataUživatele = '{ "jméno": "Jan", "věk": 35, "jeAdmin": false, "přátelé": [0,1,2,3] }'; +let dataUživatele = '{ "jméno": "Jan", "věk": 35, "jeSprávce": false, "přátelé": [0,1,2,3] }'; let uživatel = JSON.parse(dataUživatele); @@ -442,7 +442,7 @@ Toto jsou typické chyby v ručně psaném JSONu (někdy jej musíme napsat ruč let json = `{ *!*jméno*/!*: "Jan", // chyba: název vlastnosti bez uvozovek "příjmení": *!*'Novák'*/!*, // chyba: hodnota v jednoduchých uvozovkách (musí být ve dvojitých) - *!*'jeAdmin'*/!*: false // chyba: klíč v jednoduchých uvozovkách (musí být ve dvojitých) + *!*'jeSprávce'*/!*: false // chyba: klíč v jednoduchých uvozovkách (musí být ve dvojitých) "datumNarození": *!*new Date(2000, 2, 3)*/!*, // chyba: není povoleno "new", jen čisté hodnoty "přátelé": [0,1,2,3] // zde je vše v pořádku }`; diff --git a/1-js/06-advanced-functions/01-recursion/linked-list-0.svg b/1-js/06-advanced-functions/01-recursion/linked-list-0.svg index 5d23c7a4c..d3c552d8c 100644 --- a/1-js/06-advanced-functions/01-recursion/linked-list-0.svg +++ b/1-js/06-advanced-functions/01-recursion/linked-list-0.svg @@ -1 +1,272 @@ -value1nextvalue"new item"nextvalue2nextvalue3nextvalue4nextnulllist \ No newline at end of file + + + + + + + + + + hodnota + 1 + + další + + hodnota + "nový prvek" + + další + + hodnota + 2 + + další + + hodnota + 3 + + další + + hodnota + 4 + + další + null + seznam + + + diff --git a/1-js/06-advanced-functions/01-recursion/linked-list-remove-1.svg b/1-js/06-advanced-functions/01-recursion/linked-list-remove-1.svg index 2f37449c4..46ef2a82a 100644 --- a/1-js/06-advanced-functions/01-recursion/linked-list-remove-1.svg +++ b/1-js/06-advanced-functions/01-recursion/linked-list-remove-1.svg @@ -1 +1,277 @@ -value"new item"nextvalue1nextvalue2nextvalue3nextvalue4nextnulllist \ No newline at end of file + + + + + + + + + + hodnota + "nový prvek" + + další + + hodnota + 1 + + další + + hodnota + 2 + + další + + hodnota + 3 + + další + + hodnota + 4 + + další + null + seznam + + + diff --git a/1-js/06-advanced-functions/01-recursion/linked-list-split.svg b/1-js/06-advanced-functions/01-recursion/linked-list-split.svg index 6c3072130..175895c35 100644 --- a/1-js/06-advanced-functions/01-recursion/linked-list-split.svg +++ b/1-js/06-advanced-functions/01-recursion/linked-list-split.svg @@ -1 +1,250 @@ -value1nextvalue2nextvalue3nextvalue4nextnullnullsecondListlist \ No newline at end of file + + + + + + + + + + hodnota + 1 + + další + + hodnota + 2 + + další + + hodnota + 3 + + další + + hodnota + 4 + + další + null + null + druhýSeznam + seznam + + + diff --git a/1-js/06-advanced-functions/01-recursion/linked-list.svg b/1-js/06-advanced-functions/01-recursion/linked-list.svg index c02744f39..746e5811c 100644 --- a/1-js/06-advanced-functions/01-recursion/linked-list.svg +++ b/1-js/06-advanced-functions/01-recursion/linked-list.svg @@ -1 +1,232 @@ -value1nextvalue2nextvalue3nextvalue4nextnulllist \ No newline at end of file + + + + + + + + + + hodnota + 1 + + další + + hodnota + 2 + + další + + hodnota + 3 + + další + + hodnota + 4 + + další + null + seznam + + + diff --git a/1-js/06-advanced-functions/01-recursion/recursion-pow.svg b/1-js/06-advanced-functions/01-recursion/recursion-pow.svg index 9a6081b50..a7c4e3ebb 100644 --- a/1-js/06-advanced-functions/01-recursion/recursion-pow.svg +++ b/1-js/06-advanced-functions/01-recursion/recursion-pow.svg @@ -1 +1,203 @@ -pow(x,n)xx * pow(x, n-1)n == 1 ?AnoNerekurzívní volání až do n==1 \ No newline at end of file + + + + + + + + + + + mocnina(x, n) + + + + + x + + + + x * mocnina(x, n-1) + + + + + + n == 1 ? + + Ano + Ne + + + + rekurzívní volání až do n==1 + + + + diff --git a/1-js/06-advanced-functions/08-settimeout-setinterval/article.md b/1-js/06-advanced-functions/08-settimeout-setinterval/article.md index bc961cfd6..10866f044 100644 --- a/1-js/06-advanced-functions/08-settimeout-setinterval/article.md +++ b/1-js/06-advanced-functions/08-settimeout-setinterval/article.md @@ -217,7 +217,7 @@ A zde je obrázek pro vnořený `setTimeout`: ![](settimeout-interval.svg) -**Vnořený `setTimeout` zaručuje pevnou prodlevu (zde 100 ms).** +**Vnořený `setTimeout` zaručuje pevnou prodlevu (zde 100 ms) před koncem jednoho volání a začátkem následujícího.** Je to proto, že nové volání je naplánováno na konci předchozího. diff --git a/1-js/06-advanced-functions/09-call-apply-decorators/article.md b/1-js/06-advanced-functions/09-call-apply-decorators/article.md index b494f777e..8b2052a57 100644 --- a/1-js/06-advanced-functions/09-call-apply-decorators/article.md +++ b/1-js/06-advanced-functions/09-call-apply-decorators/article.md @@ -138,7 +138,7 @@ funkce.call(obj, 1, 2, 3) Obě volají funkci `funkce` s argumenty `1`, `2` a `3`. Jediný rozdíl je v tom, že `funkce.call` navíc nastaví `this` na `obj`. -Jako příklad v následujícím kódu zavoláme `řekniAhoj` v kontextu různých objektů: `řekniAhoj.call(uživatel)` spustí funkci `řekniAhoj`, které poskytne `this=uživatel`, a další řádek nastaví `this=admin`: +Jako příklad v následujícím kódu zavoláme `řekniAhoj` v kontextu různých objektů: `řekniAhoj.call(uživatel)` spustí funkci `řekniAhoj`, které poskytne `this=uživatel`, a další řádek nastaví `this=správce`: ```js run function řekniAhoj() { @@ -146,11 +146,11 @@ function řekniAhoj() { } let uživatel = { jméno: "Jan" }; -let admin = { jméno: "Admin" }; +let správce = { jméno: "Správce" }; // použitím call předáme různé objekty jako „this“ řekniAhoj.call( uživatel ); // Jan -řekniAhoj.call( admin ); // Admin +řekniAhoj.call( správce ); // Správce ``` A zde použijeme `call`, abychom zavolali `řekni` se zadaným kontextem a větou: diff --git a/1-js/06-advanced-functions/10-bind/article.md b/1-js/06-advanced-functions/10-bind/article.md index 742f18f6a..dc9425b7d 100644 --- a/1-js/06-advanced-functions/10-bind/article.md +++ b/1-js/06-advanced-functions/10-bind/article.md @@ -125,7 +125,7 @@ funkceUživatel(); // Jan */!* ``` -Zde je `funkce.bind(uživatel)` jako „vázaná varianta“ `funkce` s napevno nastaveným `this=uživatel`. +Zde je `funkce.bind(uživatel)` „vázanou variantou“ `funkce` s napevno nastaveným `this=uživatel`. Všechny argumenty se předávají do původní `funkce` beze změny, například: diff --git a/1-js/08-prototypes/01-prototype-inheritance/article.md b/1-js/08-prototypes/01-prototype-inheritance/article.md index 2804a1d99..ec2684b73 100644 --- a/1-js/08-prototypes/01-prototype-inheritance/article.md +++ b/1-js/08-prototypes/01-prototype-inheritance/article.md @@ -2,7 +2,7 @@ Při programování často chceme něco vzít a rozšířit. -Například máme objekt `uživatel` s jeho vlastnostmi a metodami a chceme vytvořit objekty `admin` a `host` jako jeho mírně pozměněné varianty. Rádi bychom použili to, co máme v objektu `uživatel`, nekopírovali ani znovu neimplementovali jeho metody, jen postavili nový objekt na jeho základu. +Například máme objekt `uživatel` s jeho vlastnostmi a metodami a chceme vytvořit objekty `správce` a `host` jako jeho mírně pozměněné varianty. Rádi bychom použili to, co máme v objektu `uživatel`, nekopírovali ani znovu neimplementovali jeho metody, jen postavili nový objekt na jeho základu. Prvek jazyka, který nám s tím pomůže, je *prototypová dědičnost*. @@ -178,7 +178,7 @@ Od nynějška volání `králík.jdi()` najde metodu rovnou v objektu a spustí Výjimkou jsou přístupové vlastnosti, jelikož přiřazení je zpracováváno setterem. Zápis do takové vlastnosti je tedy ve skutečnosti totéž jako volání funkce. -Z tohoto důvodu bude v následujícím kódu korektně fungovat `admin.celéJméno`: +Z tohoto důvodu bude v následujícím kódu korektně fungovat `správce.celéJméno`: ```js run let uživatel = { @@ -194,31 +194,31 @@ let uživatel = { } }; -let admin = { +let správce = { __proto__: uživatel, - jeAdmin: true + jesprávce: true }; -alert(admin.celéJméno); // Jan Novák (*) +alert(správce.celéJméno); // Jan Novák (*) // spustí se setter! -admin.celéJméno = "Alice Cooper"; // (**) +správce.celéJméno = "Alice Cooper"; // (**) -alert(admin.celéJméno); // Alice Cooper, stav admina modifikován +alert(správce.celéJméno); // Alice Cooper, stav správcea modifikován alert(uživatel.celéJméno); // Jan Novák, stav uživatele ochráněn ``` -Zde na řádku `(*)` má vlastnost `admin.celéJméno` getter v prototypu `uživatel`, takže se zavolá tento getter. A na řádku `(**)` má tato vlastnost v tomto prototypu setter, takže se zavolá tento setter. +Zde na řádku `(*)` má vlastnost `správce.celéJméno` getter v prototypu `uživatel`, takže se zavolá tento getter. A na řádku `(**)` má tato vlastnost v tomto prototypu setter, takže se zavolá tento setter. ## Hodnota „this“ -V uvedeném příkladu se může objevit zajímavá otázka: jaká je hodnota `this` uvnitř `set celéJméno(hodnota)`? Kam se zapíší vlastnosti `this.jméno` a `this.příjmení`: do objektu `uživatel`, nebo `admin`? +V uvedeném příkladu se může objevit zajímavá otázka: jaká je hodnota `this` uvnitř `set celéJméno(hodnota)`? Kam se zapíší vlastnosti `this.jméno` a `this.příjmení`: do objektu `uživatel`, nebo `správce`? Odpověď je jednoduchá: `this` není prototypem vůbec ovlivněno. **Nezáleží na tom, kde je metoda nalezena: zda v objektu nebo v prototypu. Při volání metody je `this` vždy objekt před tečkou.** -Volání setteru `admin.celéJméno=` tedy jako `this` použije objekt `admin`, ne `uživatel`. +Volání setteru `správce.celéJméno=` tedy jako `this` použije objekt `správce`, ne `uživatel`. To je ve skutečnosti nesmírně důležitá věc, neboť můžeme mít velký objekt obsahující mnoho metod a objekty, které z něj budou dědit. A když budou dědící objekty spouštět zděděné metody, budou modifikovat jen svůj vlastní stav a ne stav onoho velkého objektu. diff --git a/1-js/08-prototypes/02-function-prototype/proto-constructor-animal-rabbit.svg b/1-js/08-prototypes/02-function-prototype/proto-constructor-animal-rabbit.svg index ede4e1227..968bf91ec 100644 --- a/1-js/08-prototypes/02-function-prototype/proto-constructor-animal-rabbit.svg +++ b/1-js/08-prototypes/02-function-prototype/proto-constructor-animal-rabbit.svg @@ -1 +1,146 @@ -eats: truename: "White Rabbit"animalRabbitrabbit[[Prototype]]prototype \ No newline at end of file + + + + + + + + + + žere: true + + jméno: "Bílý králík" + zvíře + + Králík + králík + + + [[Prototype]] + prototype + + + diff --git a/1-js/09-classes/05-extend-natives/05-extend-natives/article.md b/1-js/09-classes/05-extend-natives/05-extend-natives/article.md new file mode 100644 index 000000000..b174de3ca --- /dev/null +++ b/1-js/09-classes/05-extend-natives/05-extend-natives/article.md @@ -0,0 +1,89 @@ + +# Rozšiřování vestavěných tříd + +Rozšiřovat lze i vestavěné třídy, například Array, Map a jiné. + +Například zde `SilnéPole` je zděděno z nativního `Array`: + +```js run +// přidáme do něj jednu další metodu (můžeme i víc) +class SilnéPole extends Array { + jePrázdné() { + return this.length === 0; + } +} + +let pole = new SilnéPole(1, 2, 5, 10, 50); +alert(pole.jePrázdné()); // false + +let filtrovanéPole = pole.filter(prvek => prvek >= 10); +alert(filtrovanéPole); // 10, 50 +alert(filtrovanéPole.jePrázdné()); // false +``` + +Všimněte si prosíme velmi zajímavé věci. Vestavěné metody jako `filter`, `map` a jiné vracejí nové objekty přesně zděděného typu `SilnéPole`. Jejich vnitřní implementace k tomu využívá vlastnost `constructor` objektu, na němž je metoda volána. + +V uvedeném příkladu: +```js +pole.constructor === SilnéPole +``` + +Když je voláno `pole.filter()`, vnitřně vytvoří nové pole výsledků voláním přesně `pole.constructor`, ne základního `Array`. To je vskutku vynikající, protože i nadále můžeme na výsledku používat metody třídy `SilnéPole`. + +A navíc si můžeme toto chování sami nastavit. + +Můžeme do třídy přidat speciální statický getter `Symbol.species`. Pokud existuje, měl by vracet konstruktor, který bude JavaScriptem vnitřně používán k vytvoření nových entit ve funkcích `map`, `filter` a podobně. + +Kdybychom chtěli, aby vestavěné metody jako `map` nebo `filter` vracely regulérní pole, můžeme v `Symbol.species` vracet `Array`, například zde: + +```js run +class SilnéPole extends Array { + jePrázdné() { + return this.length === 0; + } + +*!* + // vestavěné metody budou jako konstruktor používat toto + static get [Symbol.species]() { + return Array; + } +*/!* +} + +let pole = new SilnéPole(1, 2, 5, 10, 50); +alert(pole.jePrázdné()); // false + +// filter vytvoří nové pole s použitím pole.constructor[Symbol.species] jako konstruktoru +let filtrovanéPole = pole.filter(prvek => prvek >= 10); + +*!* +// filtrovanéPole není SilnéPole, ale Array +*/!* +alert(filtrovanéPole.jePrázdné()); // Chyba: filtrovanéPole.jePrázdné není funkce +``` + +Jak vidíte, nyní `.filter` vrací `Array`. Rozšířená funkcionalita se tedy dál nepředává. + +```smart header="Obdobně fungují ostatní kolekce" +Obdobně fungují i ostatní kolekce, např. `Map` a `Set`. I ty používají `Symbol.species`. +``` + +## Zabudované objekty nemají statickou dědičnost + +Zabudované objekty mají své vlastní statické metody, například `Object.keys`, `Array.isArray` atd. + +Jak už víme, nativní třídy se navzájem rozšiřují. Například třída `Array` rozšiřuje třídu `Object`. + +Když jedna třída rozšiřuje druhou, zpravidla z ní dědí statické i nestatické metody. To bylo podrobně vysvětleno v článku [](info:static-properties-methods#statics-and-inheritance). + +Avšak vestavěné třídy jsou výjimkou. Ty od sebe navzájem nedědí statická pole. + +Například třídy `Array` i `Date` dědí ze třídy `Object`, takže jejich instance obsahují metody z `Object.prototype`. Ale `Array.[[Prototype]]` se neodkazuje na `Object`, takže neexistuje například statická metoda `Array.keys()` (nebo `Date.keys()`). + +Na obrázku vidíme strukturu pro `Date` a `Object`: + +![](object-date-inheritance.svg) + +Jak vidíte, mezi `Date` a `Object` neexistuje žádné spojení. Jsou nezávislé, jedině `Date.prototype` dědí z `Object.prototype`. + +To je důležitý rozdíl v dědičnosti mezi vestavěnými objekty oproti tomu, co získáme použitím `extends`. diff --git a/1-js/09-classes/05-extend-natives/05-extend-natives/object-date-inheritance.svg b/1-js/09-classes/05-extend-natives/05-extend-natives/object-date-inheritance.svg new file mode 100644 index 000000000..95fda7e24 --- /dev/null +++ b/1-js/09-classes/05-extend-natives/05-extend-natives/object-date-inheritance.svg @@ -0,0 +1 @@ +constructor: Object toString: function hasOwnProperty: function ...Object.prototypeconstructor: Date toString: function getDate: function ...Date.prototypeObjectDatenew Date()[[Prototype]][[Prototype]]prototypeprototypedefineProperty keys ...now parse ...1. leden 2019 \ No newline at end of file diff --git a/1-js/10-error-handling/1-try-catch/article.md b/1-js/10-error-handling/1-try-catch/article.md index 798d3c111..daf20e907 100644 --- a/1-js/10-error-handling/1-try-catch/article.md +++ b/1-js/10-error-handling/1-try-catch/article.md @@ -631,7 +631,7 @@ Například: Úkolem globálního handleru `window.onerror` obvykle není obnovit běh skriptu -- to je v případě programátorských chyb už zřejmě nemožné, ale poslat vývojářům chybovou zprávu. -Existují i webové služby, které poskytují logování chyb pro tyto případy, například . +Existují i webové služby, které poskytují logování chyb pro tyto případy, například nebo or . Fungují následovně: diff --git a/1-js/11-async/03-promise-chaining/article.md b/1-js/11-async/03-promise-chaining/article.md index 08bf3a0cf..5a00e9ba0 100644 --- a/1-js/11-async/03-promise-chaining/article.md +++ b/1-js/11-async/03-promise-chaining/article.md @@ -248,7 +248,7 @@ fetch('/article/promise-chaining/user.json') }) .then(function(text) { // ...a zde je obsah vzdáleného souboru - alert(text); // {"name": "iliakan", "isAdmin": true} + alert(text); // {"jméno": "iliakan", "jeSprávce": true} }); ``` @@ -260,7 +260,7 @@ Pro stručnost budeme používat šipkové funkce: // totéž jako výše, ale odpověď.json() rozparsuje vzdálený obsah z JSONu fetch('/article/promise-chaining/user.json') .then(odpověď => odpověď.json()) - .then(uživatel => alert(uživatel.name)); // iliakan, získali jsme jméno uživatele + .then(uživatel => alert(uživatel.jméno)); // iliakan, získali jsme jméno uživatele ``` Nyní s načteným uživatelem něco udělejme. @@ -273,7 +273,7 @@ fetch('/article/promise-chaining/user.json') // Načteme ho jako json .then(odpověď => odpověď.json()) // Vytvoříme požadavek na GitHub - .then(uživatel => fetch(`https://api.github.com/users/${uživatel.name}`)) + .then(uživatel => fetch(`https://api.github.com/users/${uživatel.jméno}`)) // Načteme odpověď jako json .then(odpověď => odpověď.json()) // Zobrazíme obrázek avatara (uživatelGitHubu.avatar_url) na 3 sekundy (můžeme jej animovat) @@ -298,7 +298,7 @@ Například: ```js run fetch('/article/promise-chaining/user.json') .then(odpověď => odpověď.json()) - .then(uživatel => fetch(`https://api.github.com/users/${uživatel.name}`)) + .then(uživatel => fetch(`https://api.github.com/users/${uživatel.jméno}`)) .then(odpověď => odpověď.json()) *!* .then(uživatelGitHubu => new Promise(function(splň, zamítni) { // (*) @@ -316,7 +316,7 @@ fetch('/article/promise-chaining/user.json') }, 3000); })) // spustí se za 3 sekundy - .then(uživatelGitHubu => alert(`Ukončeno zobrazení uživatele ${uživatelGitHubu.name}`)); + .then(uživatelGitHubu => alert(`Ukončeno zobrazení uživatele ${uživatelGitHubu.jméno}`)); ``` Funguje to tak, že handler `.then` na řádku `(*)` nyní vrátí `new Promise`, který se usadí až po volání `splň(uživatelGitHubu)` ve funkci `setTimeout` `(**)`. Další `.then` v řetězu na to bude čekat. @@ -351,9 +351,9 @@ function zobrazAvatar(uživatelGitHubu) { // Použijeme je: načtiJson('/article/promise-chaining/user.json') - .then(uživatel => načtiUživateleGitHubu(uživatel.name)) + .then(uživatel => načtiUživateleGitHubu(uživatel.jméno)) .then(zobrazAvatar) - .then(uživatelGitHubu => alert(`Ukončeno zobrazení uživatele ${uživatelGitHubu.name}`)); + .then(uživatelGitHubu => alert(`Ukončeno zobrazení uživatele ${uživatelGitHubu.jméno}`)); // ... ``` diff --git a/1-js/11-async/03-promise-chaining/user.json b/1-js/11-async/03-promise-chaining/user.json index 32f89971a..f8ef73e40 100644 --- a/1-js/11-async/03-promise-chaining/user.json +++ b/1-js/11-async/03-promise-chaining/user.json @@ -1,4 +1,4 @@ { - "name": "iliakan", - "isAdmin": true + "jméno": "iliakan", + "jeSprávce": true } diff --git a/1-js/11-async/04-promise-error-handling/user.json b/1-js/11-async/04-promise-error-handling/user.json index 32f89971a..f8ef73e40 100644 --- a/1-js/11-async/04-promise-error-handling/user.json +++ b/1-js/11-async/04-promise-error-handling/user.json @@ -1,4 +1,4 @@ { - "name": "iliakan", - "isAdmin": true + "jméno": "iliakan", + "jeSprávce": true } diff --git a/1-js/11-async/05-promise-api/iliakan.json b/1-js/11-async/05-promise-api/iliakan.json index 32f89971a..f8ef73e40 100644 --- a/1-js/11-async/05-promise-api/iliakan.json +++ b/1-js/11-async/05-promise-api/iliakan.json @@ -1,4 +1,4 @@ { - "name": "iliakan", - "isAdmin": true + "jméno": "iliakan", + "jeSprávce": true } diff --git a/1-js/11-async/08-async-await/04-promise-all-failure/solution.md b/1-js/11-async/08-async-await/04-promise-all-failure/solution.md new file mode 100644 index 000000000..4a905be8d --- /dev/null +++ b/1-js/11-async/08-async-await/04-promise-all-failure/solution.md @@ -0,0 +1,113 @@ + +Jádro problému spočívá v tom, že `Promise.all` se okamžitě zamítne, když bude zamítnut jeden z jeho příslibů, ale neudělá nic, aby zrušilo ostatní přísliby. + +V našem případě selže druhý dotaz, takže `Promise.all` se zamítne a blok `try...catch` tuto chybu zachytí. Mezitím však ostatní přísliby *nejsou ovlivněny* -- jejich vykonávání nezávisle pokračuje. V našem případě třetí příslib za nějakou dobu vygeneruje chybu sám o sobě. A tato chyba není ničím zachycena a my ji uvidíme v konzoli. + +Tento problém je obzvláště nebezpečný v prostředích na straně serveru, například Node.js, kde nezachycená chyba může vést k havárii procesu. + +Jak to opravit? + +Ideální řešení by bylo zrušit všechny nedokončené dotazy ve chvíli, kdy jeden z nich selže. Tímto způsobem se vyhneme všem potenciálním chybám. + +Špatná zpráva však je, že volání služeb (např. `databáze.dotaz`) je často implementováno knihovnou třetí strany, která nepodporuje rušení. Pak neexistuje žádný způsob, jak volání zrušit. + +Jako alternativu si můžeme napsat vlastní obalovou funkci kolem `Promise.all`, která přidá ke každému příslibu vlastní handler `then/catch`, který je bude sledovat: výsledky se shromáždí, a pokud dojde k chybě, všechny ostatní přísliby jsou ignorovány. + +```js +function vlastníPromiseAll(přísliby) { + return new Promise((splň, zamítni) => { + const výsledky = []; + let početVýsledků = 0; + let mámeChybu = false; // po první chybě to nastavíme na true + + přísliby.forEach((příslib, index) => { + příslib + .then(výsledek => { + if (mámeChybu) return; // pokud už máme chybu, příslib ignorujeme + výsledky[index] = výsledek; + početVýsledků++; + if (početVýsledků === přísliby.length) { + splň(výsledky); // když jsou všechny výsledky připraveny - úspěch + } + }) + .catch(chyba => { + if (mámeChybu) return; // pokud už máme chybu, příslib ignorujeme + mámeChybu = true; // ouha, chyba! + zamítni(chyba); // zamítnutí při selhání + }); + }); + }); +} +``` + +Tento přístup má sám o sobě problém -- často není žádoucí volat `odpoj()`, když jsou dotazy ještě zpracovávány. + +Může být důležité, aby se všechny dotazy zpracovaly, zvláště když některé z nich provádějí důležité zápisy do databáze. + +Než tedy budeme pokračovat v provádění a nakonec se odpojíme, měli bychom počkat, než budou všechny přísliby usazeny. + +Zde je jiná implementace. Chová se podobně jako `Promise.all` -- také se vyhodnotí při první chybě, ale počká, dokud nebudou všechny přísliby usazeny. + +```js +function vlastníPromiseAllSČekáním(přísliby) { + return new Promise((splň, zamítni) => { + const výsledky = new Array(přísliby.length); + let početUsazených = 0; + let prvníChyba = null; + + přísliby.forEach((příslib, index) => { + Promise.splň(příslib) + .then(výsledek => { + výsledky[index] = výsledek; + }) + .catch(chyba => { + if (prvníChyba === null) { + prvníChyba = chyba; + } + }) + .finally(() => { + početUsazených++; + if (početUsazených === přísliby.length) { + if (prvníChyba !== null) { + zamítni(prvníChyba); + } else { + splň(výsledky); + } + } + }); + }); + }); +} +``` + +Nyní `await vlastníPromiseAllSČekáním(...)` pozastaví provádění, dokud nebudou všechny dotazy zpracovány. + +Tento přístup je spolehlivější, neboť zaručuje předvídatelný průběh provádění. + +Nakonec, kdybychom chtěli zpracovat všechny chyby, můžeme buď použít `Promise.allSettled`, nebo kolem něj napsat obal, který shromáždí všechny chyby do jediného objektu [AggregateError](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/AggregateError) a zamítne se s ním. + +```js +// počkáme na usazení všech příslibů +// pokud nebyla žádná chyba, vrátíme výsledky +// pokud byly chyby, vygenerujeme AggregateError se všemi chybami +function všechnoNeboAggregateError(přísliby) { + return Promise.allSettled(přísliby).then(výsledky => { + const chyby = []; + const hodnoty = []; + + výsledky.forEach((výsl, i) => { + if (výsl.status === 'fulfilled') { + hodnoty[i] = výsl.value; + } else { + chyby.push(výsl.reason); + } + }); + + if (chyby.length > 0) { + throw new AggregateError(chyby, 'Jeden nebo více příslibů selhalo'); + } + + return hodnoty; + }); +} +``` diff --git a/1-js/11-async/08-async-await/04-promise-all-failure/task.md b/1-js/11-async/08-async-await/04-promise-all-failure/task.md new file mode 100644 index 000000000..83ee76398 --- /dev/null +++ b/1-js/11-async/08-async-await/04-promise-all-failure/task.md @@ -0,0 +1,79 @@ + +# Nebezpečný Promise.all + +`Promise.all` je skvělý způsob, jak paralelizovat vícenásobné operace. Obzvláště se hodí, když potřebujeme vytvořit paralelní požadavky na více služeb. + +Skrývá se v něm však nebezpečí. V této úloze uvidíme jeho příklad a prozkoumáme, jak se mu vyhnout. + +Dejme tomu, že máme připojení ke vzdálené službě, například k databázi. + +Máme pro něj dvě funkce: `připoj()` a `odpoj()`. + +Když se připojíme, můžeme posílat požadavky voláním `databáze.dotaz(...)` -- asynchronní funkce, která obvykle vrátí výsledek, ale může také vygenerovat chybu. + +Jednoduchá implementace: + +```js +let databáze; + +function připoj() { + databáze = { + async dotaz(jeOk) { + if (!jeOk) throw new Error('Dotaz selhal'); + } + }; +} + +function odpoj() { + databáze = null; +} + +// zamýšlené použití: +// připoj() +// ... +// databáze.dotaz(true) pro emulaci úspěšného volání +// databáze.dotaz(false) pro emulaci neúspěšného volání +// ... +// odpoj() +``` + +Nyní zde máme problém. + +Napíšeme kód pro připojení a pošleme paralelně 3 dotazy (každý z nich trvá jinou dobu, např. 100, 200 a 300 ms), pak se odpojíme: + +```js +// pomocná funkce pro volání asynchronní funkce `fn` za `ms` milisekund +function čekej(fn, ms) { + return new Promise((splň, zamítni) => { + setTimeout(() => fn().then(splň, zamítni), ms); + }); +} + +async function spusť() { + připoj(); + + try { + await Promise.all([ + // tyto 3 paralelní úkoly trvají každý jinou dobu: 100, 200 a 300 ms + // k dosažení tohoto efektu použijeme pomocnou funkci `čekej` +*!* + čekej(() => databáze.dotaz(true), 100), + čekej(() => databáze.dotaz(false), 200), + čekej(() => databáze.dotaz(false), 300) +*/!* + ]); + } catch(chyba) { + console.log('Chyba zpracována (opravdu?)'); + } + + odpoj(); +} + +spusť(); +``` + +Dva z těchto dotazů byly neúspěšné, ale my jsme natolik chytří, že jsme volání `Promise.all` umístili do bloku `try..catch`. + +Ale to nepomůže! Tento skript ve skutečnosti vyvolá nezachycenou chybu v konzoli! + +Proč? Jak se tomu vyhnout? \ No newline at end of file diff --git a/1-js/13-modules/01-modules-intro/article.md b/1-js/13-modules/01-modules-intro/article.md index b5f1af26e..1685de8c5 100644 --- a/1-js/13-modules/01-modules-intro/article.md +++ b/1-js/13-modules/01-modules-intro/article.md @@ -156,33 +156,33 @@ Nyní uvažujme hlubší příklad. ```js // 📁 admin.js -export let admin = { +export let správce = { jméno: "Jan" }; ``` -Je-li tento modul importován z více souborů, je vyhodnocen pouze poprvé, vytvoří se objekt `admin` a ten je pak předán všem dalším importérům. +Je-li tento modul importován z více souborů, je vyhodnocen pouze poprvé, vytvoří se objekt `správce` a ten je pak předán všem dalším importérům. -Všichni importéři dostanou přesně jeden a tentýž objekt `admin`: +Všichni importéři dostanou přesně jeden a tentýž objekt `správce`: ```js // 📁 1.js -import {admin} from './admin.js'; -admin.jméno = "Petr"; +import {správce} from './admin.js'; +správce.jméno = "Petr"; // 📁 2.js -import {admin} from './admin.js'; -alert(admin.jméno); // Petr +import {správce} from './admin.js'; +alert(správce.jméno); // Petr *!* -// Jak 1.js, tak 2.js se odkazují na tentýž objekt admin +// Jak 1.js, tak 2.js se odkazují na tentýž objekt správce // Změny učiněné v 1.js jsou viditelné ve 2.js */!* ``` -Jak vidíte, když `1.js` v importovaném objektu `admin` změní vlastnost `jméno`, pak `2.js` uvidí nové `admin.jméno`. +Jak vidíte, když `1.js` v importovaném objektu `správce` změní vlastnost `jméno`, pak `2.js` uvidí nové `správce.jméno`. -To je právě proto, že modul je spuštěn pouze jednou. Vygenerují se exporty a ty jsou pak sdíleny mezi importéry, takže jestliže něco změní objekt `admin`, ostatní importéři to uvidí. +To je právě proto, že modul je spuštěn pouze jednou. Vygenerují se exporty a ty jsou pak sdíleny mezi importéry, takže jestliže něco změní objekt `správce`, ostatní importéři to uvidí. **Takové chování je ve skutečnosti velmi užitečné, protože nám umožňuje *konfigurovat* moduly.** diff --git a/1-js/99-js-misc/01-proxy/article.md b/1-js/99-js-misc/01-proxy/article.md index a017c08c8..5d6c00455 100644 --- a/1-js/99-js-misc/01-proxy/article.md +++ b/1-js/99-js-misc/01-proxy/article.md @@ -690,7 +690,7 @@ Past `get` je zde „průhledná“, vrací původní vlastnost a nic jiného ne Vypadá to, že je všechno v pořádku. Učiňme však tento příklad trochu složitějším. -Po zdědění jiného objektu `admin` z objektu `uživatel` můžeme pozorovat nesprávné chování: +Po zdědění jiného objektu `správce` z objektu `uživatel` můžeme pozorovat nesprávné chování: ```js run let uživatel = { @@ -707,17 +707,17 @@ let uživatelProxy = new Proxy(uživatel, { }); *!* -let admin = { +let správce = { __proto__: uživatelProxy, - _jméno: "Admin" + _jméno: "Správce" }; -// Očekáváme: Admin -alert(admin.jméno); // vypíše: Host (?!?) +// Očekáváme: Správce +alert(správce.jméno); // vypíše: Host (?!?) */!* ``` -Načtení `admin.jméno` by mělo vrátit `"Admin"`, ne `"Host"`! +Načtení `správce.jméno` by mělo vrátit `"Správce"`, ne `"Host"`! V čem je problém? Udělali jsme snad něco špatně s dědičností? @@ -725,13 +725,13 @@ Pokud však odstraníme proxy, bude všechno fungovat tak, jak očekáváme. Problém je ve skutečnosti v proxy na řádku `(*)`. -1. Když načítáme `admin.jméno`, objekt `admin` takovou vlastnost nemá, a proto hledání přejde k jeho prototypu. +1. Když načítáme `správce.jméno`, objekt `správce` takovou vlastnost nemá, a proto hledání přejde k jeho prototypu. 2. Prototypem je `uživatelProxy`. 3. Když načítáme vlastnost `jméno` z proxy, spustí se jeho past `get` a na řádku `(*)` ji vrátí z původního objektu jako `cíl[vlastnost]`. Volání `cíl[vlastnost]`, když `vlastnost` je getter, spustí kód tohoto getteru v kontextu `this=cíl`. Výsledkem je tedy `this._jméno` z původního objektu `cíl`, což je: z objektu `uživatel`. -Abychom takové situace opravili, potřebujeme `příjemce`, třetí argument pasti `get`. Ten udržuje správné `this`, které bude předáno getteru. V našem případě to je `admin`. +Abychom takové situace opravili, potřebujeme `příjemce`, třetí argument pasti `get`. Ten udržuje správné `this`, které bude předáno getteru. V našem případě to je `správce`. Jak předat kontext getteru? Pro běžnou funkci bychom mohli použít `call/apply`, ale tohle je getter, ten se „nevolá“, jenom se k němu přistupuje. @@ -748,7 +748,7 @@ let uživatel = { }; let uživatelProxy = new Proxy(uživatel, { - get(cíl, vlastnost, příjemce) { // příjemce = admin + get(cíl, vlastnost, příjemce) { // příjemce = správce *!* return Reflect.get(cíl, vlastnost, příjemce); // (*) */!* @@ -756,17 +756,17 @@ let uživatelProxy = new Proxy(uživatel, { }); -let admin = { +let správce = { __proto__: uživatelProxy, - _jméno: "Admin" + _jméno: "Správce" }; *!* -alert(admin.jméno); // Admin +alert(správce.jméno); // Správce */!* ``` -Nyní je getteru předán `příjemce`, který si udržuje odkaz na správné `this` (což je `admin`), pomocí `Reflect.get` na řádku `(*)`. +Nyní je getteru předán `příjemce`, který si udržuje odkaz na správné `this` (což je `správce`), pomocí `Reflect.get` na řádku `(*)`. Tuto past můžeme ještě zkrátit: diff --git a/1-js/99-js-misc/02-eval/article.md b/1-js/99-js-misc/02-eval/article.md index 86a718b48..a415d435c 100644 --- a/1-js/99-js-misc/02-eval/article.md +++ b/1-js/99-js-misc/02-eval/article.md @@ -54,7 +54,7 @@ eval("x = 10"); alert(x); // 10, hodnota změněna ``` -Ve striktním režimu má `eval` své vlastní lexikální prostředí, takže funkce a proměnné deklarované uvnitř `eval` nejsou viditelné venku: +Ve striktním režimu má `eval` své vlastní lexikální prostředí, takže funkce a proměnné deklarované uvnitř `eval` nejsou viditelné zvenčí: ```js untrusted refresh run // pamatujte: 'use strict' je ve spustitelných příkladech standardně zapnuté @@ -69,15 +69,15 @@ Bez `use strict` nemá `eval` své vlastní lexikální prostředí, takže bych ## Použití „eval“ -V moderním programování se `eval` používá velmi vzácně. Často se říká, že „eval je zlo“ *(anglicky „eval is evil“ -- pozn. překl.)*. +V moderním programování se `eval` používá velmi vzácně. Často se říká, že „eval je zlo“ (anglicky „eval is evil“). -Důvod je jednoduchý: před dávnými, dávnými časy býval JavaScript mnohem slabší jazyk a mnoho věcí bylo možné provést jedině pomocí `eval`. Ale tahle doba pominula už před deseti lety. +Důvod je jednoduchý: před dávnými, dávnými časy byl JavaScript mnohem slabší jazyk a mnoho věcí bylo možné provést jedině pomocí `eval`. Ale tahle doba pominula už před deseti lety. -V současnosti není téměř žádný důvod, proč `eval` používat. Pokud ho někdo používá, je velká šance, že se dá nahradit nějakou moderní jazykovou konstrukcí nebo [JavaScriptovým modulem](info:modules). +V současnosti není téměř žádný důvod, proč `eval` používat. Pokud ho někdo používá, je velká šance, že ho lze nahradit nějakým moderním jazykovým konstruktem nebo [JavaScriptovým modulem](info:modules). Prosíme všimněte si, že jeho schopnost přistupovat k vnějším proměnným má vedlejší efekty. -Minifikátory kódu (nástroje používané před odesláním JS do produkce, aby jej zkomprimovaly) přejmenovávají lokální proměnné na kratší (např. `a`, `b` atd.), aby kód zkrátily. To je obvykle bezpečné, ale při použití `eval` ne, protože vyhodnocovaný řetězec kódu může k lokálním proměnným přistupovat. Minifikátory tedy toto přejmenování neprovádějí u proměnných, které mohou být viditelné z `eval`. To negativně ovlivňuje poměr komprese kódu. +Minifikátory kódu (nástroje používané před odesláním JS do produkce, aby jej zkomprimovaly) přejmenovávají lokální proměnné na kratší (např. `a`, `b` atd.), aby kód zkrátily. To je obvykle bezpečné, ale při použití `eval` ne, protože vyhodnocovaný řetězec kódu může k lokálním proměnným přistupovat. Minifikátory tedy u proměnných, které mohou být viditelné z `eval`, toto přejmenování neprovádějí. To negativně ovlivňuje poměr komprese kódu. Rovněž používání vnějších lokálních proměnných uvnitř `eval` se považuje za špatnou programátorskou praktiku, protože ztěžuje údržbu kódu. @@ -103,12 +103,12 @@ let f = new Function('a', 'alert(a)'); f(5); // 5 ``` -Konstrukce `new Function` je vysvětlena v kapitole . Vytvoří funkci z řetězce, rovněž v globálním rozsahu platnosti. Funkce tedy neuvidí lokální proměnné. Je však mnohem čistší předat je explicitně jako argumenty, tak jako v uvedeném příkladu. +Konstrukt `new Function` je vysvětlen v kapitole . Vytvoří funkci z řetězce, rovněž v globálním rozsahu platnosti. Funkce tedy neuvidí lokální proměnné. Je však mnohem čistší předat je explicitně jako argumenty, tak jako v uvedeném příkladu. ## Shrnutí Volání `eval(kód)` spustí řetězec kódu a vrátí výsledek posledního příkazu. - V moderním JavaScriptu se používá málokdy, jelikož obvykle není zapotřebí. - Může přistupovat k vnějším lokálním proměnným. To se považuje za špatnou praktiku. -- Místo toho k vyhodnocení kódu v globálním rozsahu platnosti použijte `window.eval(kód)`. +- K vyhodnocení kódu v globálním rozsahu platnosti místo něj použijte `window.eval(kód)`. - Nebo, jestliže váš kód potřebuje data z vnějšího rozsahu, použijte `new Function` a předejte je jako argumenty. \ No newline at end of file diff --git a/1-js/99-js-misc/03-currying-partials/article.md b/1-js/99-js-misc/03-currying-partials/article.md index 4057774f8..b21976f2c 100644 --- a/1-js/99-js-misc/03-currying-partials/article.md +++ b/1-js/99-js-misc/03-currying-partials/article.md @@ -3,21 +3,21 @@ libs: --- -# Currying +# Curryování -[Currying neboli curryování](https://en.wikipedia.org/wiki/Currying) je pokročilá technika práce s funkcemi. Používá se nejen v JavaScriptu, ale i v jiných jazycích. +[Curryování neboli currying](https://en.wikipedia.org/wiki/Currying) je pokročilá technika práce s funkcemi. Používá se nejen v JavaScriptu, ale i v jiných jazycích. -Currying je transformace funkce, která přeloží funkci volatelnou způsobem `f(a, b, c)` na volatelnou způsobem `f(a)(b)(c)`. +Curryování je transformace funkce, která přeloží funkci volatelnou způsobem `f(a, b, c)` na funkci volatelnou způsobem `f(a)(b)(c)`. -Currying nevolá funkci, jen ji transformuje. +Curryování nevolá funkci, jen ji transformuje. Nejprve se podívejme na příklad, abychom lépe porozuměli tomu, o čem se tady mluví, a pak na praktické aplikace. -Vytvořme pomocnou funkci `curry(f)`, která provádí currying dvouargumentové funkce `f`. Jinými slovy, `curry(f)` na dvouargumentové funkci `f(a, b)` ji přeloží na funkci, která se bude spouštět jako `f(a)(b)`: +Vytvořme pomocnou funkci `curry(f)`, která provádí curryování dvouargumentové funkce `f`. Jinými slovy, `curry(f)` na dvouargumentové funkci `f(a, b)` ji přeloží na funkci, která se bude spouštět jako `f(a)(b)`: ```js run *!* -function curry(f) { // curry(f) provede curryingovou transformaci +function curry(f) { // curry(f) provede curryovací transformaci return function(a) { return function(b) { return f(a, b); @@ -36,13 +36,13 @@ let curryovanýSoučet = curry(součet); alert( curryovanýSoučet(1)(2) ); // 3 ``` -Jak vidíte, implementace je přímočará: jsou to pouhé dva wrappery. +Jak vidíte, implementace je přímočará: jsou to pouhé dva obaly. -- Výsledkem `curry(func)` je wrapper `function(a)`. -- Když je zavolán způsobem `curryovanýSoučet(1)`, argument se uloží do lexikálního prostředí a vrátí se nový wrapper `function(b)`. -- Pak je tento wrapper volán s argumentem `2` a předá volání původní funkci `součet`. +- Výsledkem `curry(func)` je obal `function(a)`. +- Když je zavolán způsobem `curryovanýSoučet(1)`, argument se uloží do lexikálního prostředí a vrátí se nový obal `function(b)`. +- Pak je tento obal volán s argumentem `2` a předá volání původní funkci `součet`. -Pokročilejší implementace curryingu, např. [_.curry](https://lodash.com/docs#curry) z knihovny lodash, vrátí wrapper, který umožní, aby funkce mohla být volána jak normálně, tak parciálně: +Pokročilejší implementace curryování, např. [_.curry](https://lodash.com/docs#curry) z knihovny lodash, vrátí obal, který umožní volat funkci jak obvyklým způsobem, tak parciálně: ```js run function součet(a, b) { @@ -55,11 +55,11 @@ alert( curryovanýSoučet(1, 2) ); // 3, stále volatelná normálně alert( curryovanýSoučet(1)(2) ); // 3, voláno parciálně ``` -## Currying? K čemu to je? +## Curryování? K čemu to je? Abychom pochopili výhody, potřebujeme cenný příklad z reálného života. -Mějme například logovací funkci `log(datum, důležitost, zpráva)`, která naformátuje a vypíše informaci. Ve skutečných projektech mají takové funkce mnoho užitečných možností, např. posílání logů po síti, zde jenom zavoláme `alert`: +Mějme například logovací funkci `log(datum, důležitost, zpráva)`, která naformátuje a vypíše zadané informace. Ve skutečných projektech mají takové funkce mnoho užitečných možností, např. posílání logů po síti, zde jenom zavoláme `alert`: ```js function log(datum, důležitost, zpráva) { @@ -76,13 +76,13 @@ log = _.curry(log); Pak bude `log` fungovat normálně: ```js -log(new Date(), "DEBUG", "nějaký debug"); // log(a, b, c) +log(new Date(), "LADĚNÍ", "nějaké ladění"); // log(a, b, c) ``` ...Ale bude fungovat i v curryované formě: ```js -log(new Date())("DEBUG")("nějaký debug"); // log(a)(b)(c) +log(new Date())("LADĚNÍ")("nějaké ladění"); // log(a)(b)(c) ``` Nyní můžeme snadno vytvořit pohodlnou funkci pro aktuální logování: @@ -97,21 +97,21 @@ logNyní("INFO", "zpráva"); // [HH:mm] INFO zpráva Nyní `logNyní` je `log` s pevným prvním argumentem, jinými slovy „parciálně aplikovaná funkce“ nebo krátce „parciální funkce“. -Můžeme jít dál a vytvořit pohodlnou funkci pro aktuální logování debugů: +Můžeme jít dál a vytvořit pohodlnou funkci pro aktuální logování ladění: ```js -let debugNyní = logNyní("DEBUG"); +let laděníNyní = logNyní("LADĚNÍ"); -debugNyní("zpráva"); // [HH:mm] DEBUG zpráva +laděníNyní("zpráva"); // [HH:mm] LADĚNÍ zpráva ``` Tedy: -1. Po curryingu nic neztratíme: `log` se stále dá volat normálně. +1. Po curryování nic neztratíme: `log` se stále dá volat běžným způsobem. 2. Můžeme snadno generovat parciální funkce, např. pro logování s dnešním datem. -## Pokročilá implementace curryingu +## Pokročilá implementace curryování -V případě, že byste chtěli zajít do detailů, zde je „pokročilá“ implementace curryingu pro víceargumentové funkce, kterou bychom mohli použít výše. +Pro případ, že byste chtěli zajít do detailů, je zde „pokročilá“ implementace curryování pro víceargumentové funkce, kterou bychom mohli použít výše. Je opravdu krátká: @@ -141,13 +141,13 @@ function součet(a, b, c) { let curryovanýSoučet = curry(součet); alert( curryovanýSoučet(1, 2, 3) ); // 6, stále normálně volatelná -alert( curryovanýSoučet(1)(2,3) ); // 6, currying 1. argumentu -alert( curryovanýSoučet(1)(2)(3) ); // 6, úplný currying +alert( curryovanýSoučet(1)(2,3) ); // 6, curryování 1. argumentu +alert( curryovanýSoučet(1)(2)(3) ); // 6, úplné curryování ``` Nová funkce `curry` může vypadat komplikovaně, ale ve skutečnosti je snadné jí porozumět. -Výsledkem volání `curry(funkce)` je wrapper `curryovaná`, který vypadá takto: +Výsledkem volání `curry(funkce)` je obal `curryovaná`, který vypadá takto: ```js // funkce je funkce, která se má transformovat @@ -162,27 +162,27 @@ function curryovaná(...args) { }; ``` -Když ji spustíme, obsahuje dvě výkonové větve `if`: +Když ji spustíme, obsahuje dvě běhové větve `if`: 1. Je-li počet předaných argumentů `args` stejný nebo větší, než v definici původní funkce (`funkce.length`), pak jí jen předáme volání pomocí `funkce.apply`. -2. V opačném případě získáme parciální funkci: ještě funkci `funkce` nebudeme volat. Místo toho se vrátí další wrapper, který znovu aplikuje funkci `curryovaná` a poskytne jí předchozí argumenty společně s novými. +2. V opačném případě získáme parciální funkci: ještě funkci `funkce` nebudeme volat. Místo toho se vrátí další obal, který znovu aplikuje funkci `curryovaná` a poskytne jí předchozí argumenty společně s novými. Když ji pak znovu zavoláme, získáme buď novou parciální funkci (nemáme-li ještě dost argumentů), nebo nakonec výsledek. ```smart header="Jen pro funkce s pevnou délkou" -Currying vyžaduje, aby funkce měla pevný počet argumentů. +Curryování vyžaduje, aby funkce měla pevný počet argumentů. Funkci, která používá zbytkové parametry, např. `f(...args)`, nelze tímto způsobem curryovat. ``` -```smart header="Víc než jen currying" -Podle definice by currying měl převést `součet(a, b, c)` na `součet(a)(b)(c)`. +```smart header="Víc než jen curryování" +Podle definice by curryování mělo převést `součet(a, b, c)` na `součet(a)(b)(c)`. -Většina implementací curryingu v JavaScriptu je však pokročilá, jak bylo popsáno: udržují funkci volatelnou i ve víceargumentové variantě. +Většina implementací curryování v JavaScriptu je však pokročilá, jak bylo uvedeno: udržují funkci volatelnou i ve víceargumentové variantě. ``` ## Shrnutí -*Currying* je transformace, která umožní volat `f(a,b,c)` jako `f(a)(b)(c)`. Implementace v JavaScriptu obvykle současně ponechají funkci volatelnou normálně a vrátí parciální funkci, není-li poskytnuto dost argumentů. +*Curryování* je transformace, která umožní volat `f(a,b,c)` jako `f(a)(b)(c)`. Implementace v JavaScriptu obvykle současně ponechají funkci volatelnou normálně, ale není-li poskytnuto dost argumentů, vrátí parciální funkci. -Currying nám umožní snadno získat parciální funkci. Jak jsme viděli v příkladu s logováním, univerzální tříargumentová funkce `log(datum, důležitost, zpráva)` nám po curryingu vydá parciální funkci, když je volána s jedním argumentem (např. `log(datum)`) nebo se dvěma argumenty (např. `log(datum, důležitost)`). +Curryování nám umožní snadno získat parciální funkci. Jak jsme viděli v příkladu s logováním, univerzální tříargumentová funkce `log(datum, důležitost, zpráva)` nám po curryování vydá parciální funkci, když je volána s jedním argumentem (např. `log(datum)`) nebo se dvěma argumenty (např. `log(datum, důležitost)`). diff --git a/1-js/99-js-misc/04-reference-type/2-check-syntax/solution.md b/1-js/99-js-misc/04-reference-type/2-check-syntax/solution.md index d8e53fc03..a59d0015f 100644 --- a/1-js/99-js-misc/04-reference-type/2-check-syntax/solution.md +++ b/1-js/99-js-misc/04-reference-type/2-check-syntax/solution.md @@ -11,7 +11,7 @@ let uživatel = { (uživatel.jdi)() // chyba! ``` -Chybová zpráva ve většině prohlížečů nám nedává mnoho informací o tom, co bylo špatně. +Ve většině prohlížečů nám chybová zpráva nedává mnoho informací o tom, co bylo špatně. **Chyba se objevila proto, že za `uživatel = {...}` chybí středník.** diff --git a/1-js/99-js-misc/04-reference-type/3-why-this/solution.md b/1-js/99-js-misc/04-reference-type/3-why-this/solution.md index e8afcb837..4aa1f8c78 100644 --- a/1-js/99-js-misc/04-reference-type/3-why-this/solution.md +++ b/1-js/99-js-misc/04-reference-type/3-why-this/solution.md @@ -16,7 +16,7 @@ Zde je vysvětlení. 4. Podobně jako `(3)`, nalevo od závorek `()` máme výraz. -Abychom vysvětlili chování `(3)` a `(4)`, musíme si vzpomenout, že accessory vlastností (tečka nebo hranaté závorky) vracejí hodnotu referenčního typu. +Abychom vysvětlili chování `(3)` a `(4)`, musíme si vzpomenout, že operátory přístupu k vlastnostem (tečka nebo hranaté závorky) vracejí hodnotu referenčního typu. Jakákoli operace na ní kromě volání metody (např. přiřazení `=`, nebo `||`) ji změní na obyčejnou hodnotu, která neobsahuje informaci umožňující nastavit `this`. diff --git a/1-js/99-js-misc/04-reference-type/3-why-this/task.md b/1-js/99-js-misc/04-reference-type/3-why-this/task.md index 85ffb6dfd..dd61240f5 100644 --- a/1-js/99-js-misc/04-reference-type/3-why-this/task.md +++ b/1-js/99-js-misc/04-reference-type/3-why-this/task.md @@ -4,7 +4,7 @@ importance: 3 # Vysvětlete hodnotu „this“ -V níže uvedeném kódu jsme zamýšleli volat metodu `obj.jdi()` čtyřikrát za sebou. +V následujícím kódu jsme měli v úmyslu volat metodu `obj.jdi()` čtyřikrát za sebou. Avšak volání `(1)` a `(2)` fungují jinak než `(3)` a `(4)`. Proč? diff --git a/1-js/99-js-misc/04-reference-type/article.md b/1-js/99-js-misc/04-reference-type/article.md index bab8dbc40..d28cf60e0 100644 --- a/1-js/99-js-misc/04-reference-type/article.md +++ b/1-js/99-js-misc/04-reference-type/article.md @@ -1,10 +1,10 @@ # Referenční typ -```warn header="Hloubková vlastnost jazyka" +```warn header="Hlubší vlastnost jazyka" Tento článek se zabývá pokročilým tématem, abychom lépe porozuměli určitým okrajovým případům. -Není důležité. Mnoho zkušených vývojářů žije šťastně i přesto, že je neznají. Přečtěte si ho, pokud chcete vědět, jak fungují věci „pod kapotou“. +Toto téma není důležité. Mnoho zkušených vývojářů žije šťastně i bez jeho znalosti. Článek si přečtěte, pokud chcete vědět, jak fungují věci „pod kapotou“. ``` Dynamicky vyhodnocované volání metody může ztratit `this`. @@ -20,7 +20,7 @@ let uživatel = { uživatel.ahoj(); // funguje -// nyní zavolejme uživatel.ahoj nebo uživatel.nashle podle jména +// nyní podle jména zavolejme uživatel.ahoj nebo uživatel.nashle *!* (uživatel.jméno == "Jan" ? uživatel.ahoj : uživatel.nashle)(); // Chyba! */!* @@ -72,13 +72,13 @@ Zde `ahoj = uživatel.ahoj` vloží funkci do proměnné a ta je pak na posledn **Aby volání `uživatel.ahoj()` fungovalo, JavaScript používá trik -- tečka `'.'` nevrací funkci, ale hodnotu speciálního [referenčního typu](https://tc39.github.io/ecma262/#sec-reference-specification-type).** -Referenční typ je „specifikační typ“. Nemůžeme jej explicitně používat, ale je používán interně jazykem. +Referenční typ je „specifikační typ“. Nemůžeme jej explicitně používat, ale je používán vnitřně jazykem. Hodnotou referenčního typu je tříhodnotová kombinace `(base, name, strict)`, kde: - `base` (základ) je objekt. - `name` (název) je název vlastnosti. -- `strict` je true, pokud je použito `use strict`. +- `strict` (striktní) je true, pokud je použito `use strict`. Výsledkem přístupu k vlastnosti `uživatel.ahoj` není funkce, ale hodnota referenčního typu. Pro `uživatel.ahoj` ve striktním režimu to je: @@ -89,20 +89,20 @@ Výsledkem přístupu k vlastnosti `uživatel.ahoj` není funkce, ale hodnota re Když se na referenčním typu zavolají závorky `()`, obdrží úplnou informaci o objektu a jeho metodě a mohou tedy nastavit správné `this` (v tomto případě `uživatel`). -Referenční typ je speciální „prostřednický“ interní typ, jehož účelem je předat informaci z tečky `.` volajícím závorkám `()`. +Referenční typ je speciální „zprostředkovatelský“ interní typ, jehož účelem je předat informaci z tečky `.` volajícím závorkám `()`. Jakákoli jiná operace, např. přiřazení `ahoj = uživatel.ahoj`, celý referenční typ zahodí, vezme hodnotu `uživatel.ahoj` (funkci) a předá ji dál. Jakákoli další operace tedy „ztratí“ `this`. -Výsledkem tedy je, že hodnota `this` se předá správně jen tehdy, je-li funkce volána přímo syntaxí tečky `obj.metoda()` nebo hranatých závorek `obj['metoda']()` (obojí zde provádí totéž). Existují různé způsoby, jak tento problém vyřešit, např. [funkce.bind()](/bind#solution-2-bind). +Výsledkem tedy je, že hodnota `this` se předá správně jen tehdy, je-li funkce volána přímo pomocí syntaxe tečky `obj.metoda()` nebo hranatých závorek `obj['metoda']()` (obojí zde provádí totéž). Existují různé způsoby, jak tento problém vyřešit, např. [funkce.bind()](/bind#solution-2-bind). ## Shrnutí Referenční typ je interní jazykový typ. -Načtení vlastnosti, např. pomocí tečky `.` v `obj.metoda()`, nevrací přesně hodnotu vlastnosti, ale speciální hodnotu „referenčního typu“, v níž je uložena jak hodnota vlastnosti, tak objekt, z něhož byla vzata. +Načtení vlastnosti, např. pomocí tečky `.` v `obj.metoda()`, nevrací přesně hodnotu vlastnosti, ale speciální hodnotu „referenčního typu“, v níž je uložena jak hodnota vlastnosti, tak objekt, z něhož byla převzata. To je proto, aby následné volání metody `()` mohlo získat objekt a nastavit jej jako `this`. Při všech ostatních operacích se z referenčního typu automaticky stává hodnota vlastnosti (v našem případě funkce). -Celá tato mechanika je před našima očima ukryta. Záleží na ní jen v krajních případech, např. když je metoda dynamicky získána z objektu použitím výrazu. +Celá tato mechanika je před našima očima ukryta. Záleží na ní jen v krajních případech, například když je metoda získána z objektu dynamicky použitím výrazu. diff --git a/1-js/99-js-misc/05-bigint/article.md b/1-js/99-js-misc/05-bigint/article.md index 998bec9f5..87031f0dc 100644 --- a/1-js/99-js-misc/05-bigint/article.md +++ b/1-js/99-js-misc/05-bigint/article.md @@ -1,10 +1,10 @@ -# BigInt +# Typ BigInt [recent caniuse="bigint"] `BigInt` je speciální číselný typ, který poskytuje podporu celých čísel libovolné délky. -Číslo typu BigInt se vytvoří přidáním písmene `n` na konec celočíselného literálu nebo voláním funkce `BigInt`, která vytváří biginty z řetězců, čísel apod. +Číslo typu BigInt se vytvoří přidáním písmene `n` na konec celočíselného literálu nebo voláním funkce `BigInt`, která vytváří biginty z řetězců, čísel a podobně. ```js const bigint = 1234567890123456789012345678901234567890n; @@ -32,7 +32,7 @@ Nemůžeme směšovat biginty a běžná čísla: alert(1n + 2); // Chyba: Nelze míchat dohromady BigInt a jiné typy ``` -Když je potřeba, měli bychom je explicitně konvertovat: použitím buď `BigInt()`, nebo `Number()`, například: +Když je potřeba, měli bychom je explicitně konvertovat použitím buď `BigInt()`, nebo `Number()`, například: ```js run let bigint = 1n; @@ -99,7 +99,7 @@ alert( 0n || 2 ); // 2 (0n se považuje za nepravdivé) ## Polyfilly -Polyfillování bigintů je problematické. Příčinou je, že mnoho JavaScriptových operátorů, např. `+`, `-` a podobně, se chová na bigintech jinak oproti běžným číslům. +Polyfillování bigintů je problematické. Příčinou je, že mnoho JavaScriptových operátorů, např. `+`, `-` a podobně, se chová na bigintech odlišně oproti běžným číslům. Například dělení bigintů vrátí vždy bigint (zaokrouhlený, je-li to nutné). @@ -107,7 +107,7 @@ Aby polyfill mohl takové chování emulovat, musel by analyzovat kód a nahradi Dosud tedy není dobře znám žádný dobrý polyfill. -Jinou cestičku kolem ovšem nabízejí vývojáři knihovny [JSBI](https://github.com/GoogleChromeLabs/jsbi). +Jinou cestičku kolem bigintů však nabízejí vývojáři knihovny [JSBI](https://github.com/GoogleChromeLabs/jsbi). Tato knihovna implementuje velká čísla svými vlastními metodami. Můžeme je používat místo nativních bigintů: @@ -118,11 +118,11 @@ Tato knihovna implementuje velká čísla svými vlastními metodami. Můžeme j | Odčítání | `c = a - b` | `c = JSBI.subtract(a, b)` | | ... | ... | ... | -...A pak použít polyfill (plugin Babel) ke konverzi volání JSBI na nativní biginty pro prohlížeče, které je podporují. +...A pak použít polyfill (zásuvný modul Babel) ke konverzi volání JSBI na nativní biginty pro prohlížeče, které je podporují. -Jinými slovy, tento přístup nám navrhuje, abychom místo používání nativních bigintů psali kód v JSBI. Avšak JSBI interně pracuje s čísly jako s biginty a emuluje je způsobem blízkým specifikaci, takže kód bude „připraven pro biginty“. +Jinými slovy, tento přístup nám navrhuje, abychom místo používání nativních bigintů psali kód v JSBI. Avšak JSBI vnitřně pracuje s čísly jako s biginty a emuluje je způsobem blízkým specifikaci, takže kód bude „připraven pro biginty“. -Takový kód s JSBI můžeme používat „tak, jak je“ na enginech, které biginty nepodporují, i na těch, které ano -- polyfill bude konvertovat volání na nativní biginty. +Takový kód s JSBI můžeme používat beze změny na motorech, které biginty nepodporují, i na těch, které je podporují -- polyfill bude konvertovat volání na nativní biginty. ## Odkazy diff --git a/1-js/99-js-misc/06-unicode/article.md b/1-js/99-js-misc/06-unicode/article.md index 11f813bc7..649e3e90e 100644 --- a/1-js/99-js-misc/06-unicode/article.md +++ b/1-js/99-js-misc/06-unicode/article.md @@ -1,11 +1,11 @@ -# Unicode, interní reprezentace řetězce +# Unicode, vnitřní reprezentace řetězce ```warn header="Pokročilá znalost" -Tato kapitola se hlouběji zabývá interní reprezentací řetězců. Tato znalost vám bude užitečná, jestliže plánujete pracovat s emoji, vzácnými matematickými nebo hieroglyfickými znaky nebo jinými vzácnými symboly. +Tato kapitola se hlouběji zabývá vnitřní reprezentací řetězců. Tato znalost vám bude užitečná, jestliže plánujete pracovat s emoji, vzácnými matematickými nebo hieroglyfickými znaky nebo jinými vzácnými symboly. ``` -Jak už víme, řetězce v JavaScriptu jsou založeny na [Unicode](https://cs.wikipedia.org/wiki/Unicode): každý znak představuje posloupnost 1-4 bytů. +Jak už víme, řetězce v JavaScriptu jsou založeny na [Unicode](https://cs.wikipedia.org/wiki/Unicode): každý znak je reprezentován posloupností 1 až 4 bytů. JavaScript nám umožňuje vložit znak do řetězce specifikací jeho hexadecimálního kódu v Unicode pomocí jednoho z následujících tří zápisů: @@ -13,7 +13,7 @@ JavaScript nám umožňuje vložit znak do řetězce specifikací jeho hexadecim `XX` musí být dvě hexadecimální číslice s hodnotou mezi `00` a `FF`, pak `\xXX` je znak, jehož kód v Unicode je `XX`. - Protože zápis `\xXX` podporuje jen dvě hexadecimální číslice, může být použit jedině pro prvních 256 znaků Unicode. + Protože zápis `\xXX` podporuje jen dvě hexadecimální číslice, může být použit jen pro prvních 256 znaků Unicode. Těchto prvních 256 znaků obsahuje latinskou abecedu, většinu základních syntaktických znaků a některé další. Například `"\x7A"` je totéž jako `"z"` (Unicode `U+007A`). @@ -26,30 +26,30 @@ JavaScript nám umožňuje vložit znak do řetězce specifikací jeho hexadecim `XXXX` musí být přesně 4 hexadecimální číslice s hodnotou mezi `0000` a `FFFF`, pak `\uXXXX` je znak, jehož kód v Unicode je `XXXX`. - Tímto zápisem mohou být reprezentovány i znaky, jejichž hodnoty v Unicode jsou větší než `U+FFFF`, ale v takovém případě musíme použít takzvaný náhradní pár (o náhradních párech pohovoříme později v této kapitole). + Tímto zápisem mohou být reprezentovány i znaky, jejichž hodnoty v Unicode jsou větší než `U+FFFF`, ale v takovém případě musíme použít takzvaný zástupný pár (o zástupných párech pohovoříme později v této kapitole). ```js run - alert( "\u00A9" ); // ©, totéž jako \xA9 s použitím 4-číslicového hexadecimálního zápisu + alert( "\u00A9" ); // ©, totéž jako \xA9 s použitím 4-ciferného hexadecimálního zápisu alert( "\u044F" ); // я, písmeno z kyrilice (azbuky) alert( "\u2191" ); // ↑, symbol šipky nahoru ``` - `\u{X…XXXXXX}` - `X…XXXXXX` musí být hexadecimální hodnota 1 až 6 bytů mezi `0` a `10FFFF` (nejvyšší kódový bod definovaný v Unicode). Tento zápis nám umožňuje snadno reprezentovat všechny existující znaky v Unicode. + `X…XXXXXX` musí být hexadecimální hodnota 1 až 6 bytů mezi `0` a `10FFFF` (nejvyšší kódová hodnota definovaná v Unicode). Tento zápis nám umožňuje snadno reprezentovat všechny existující znaky v Unicode. ```js run alert( "\u{20331}" ); // 佫, vzácný čínský znak (dlouhý Unicode) alert( "\u{1F60D}" ); // 😍, symbol usmívající se tváře (další dlouhý Unicode) ``` -## Náhradní páry +## Zástupné páry -Všechny často používané znaky mají 2-bytové kódy (4 hexadecimální číslice). Písmena ve většině evropských jazyků, číslice a základní sjednocené ideografické sady CJK (CJK -- pro čínské, japonské a korejské písmenné soustavy) mají 2-bytovou reprezentaci. +Všechny často používané znaky mají 2-bytové kódy (4 hexadecimální číslice). Písmena ve většině evropských jazyků, číslice a základní sjednocené ideografické sady CJK (CJK -- pro čínské, japonské a korejské písemné soustavy) mají 2-bytovou reprezentaci. JavaScript byl původně založen na kódování UTF-16, které umožňovalo jen 2 byty na znak. Avšak 2 byty umožňují jen 65536 kombinací, a to pro každý možný symbol v Unicode nestačí. -Vzácné symboly, které vyžadují více než 2 byty, jsou tedy zakódovány dvojicí 2-bytových znaků nazývanou „náhradní pár“ '(„surrogate pair“). +Vzácné symboly, které vyžadují více než 2 byty, jsou tedy zakódovány dvojicí 2-bytových znaků nazývanou „zástupný pár“ („surrogate pair“). Vedlejším efektem je, že délka takových symbolů je `2`: @@ -59,39 +59,38 @@ alert( '😂'.length ); // 2, TVÁŘ SE SLZAMI RADOSTI alert( '𩷶'.length ); // 2, vzácný čínský znak ``` -Je to proto, že v době, kdy byl JavaScript vytvořen, ještě náhradní páry neexistovaly, a proto nejsou jazykem správně zpracovávány! +Je to proto, že v době, kdy JavaScript vznikl, ještě zástupné páry neexistovaly, a proto nejsou jazykem správně zpracovávány! -Ve skutečnosti máme v každém z výše uvedených řetězců jediný symbol, ale vlastnost `length` ukazuje délku `2`. +Ve skutečnosti máme v každém z uvedených řetězců jediný symbol, ale vlastnost `length` ukazuje délku `2`. -Také načtení symbolu může být matoucí, jelikož většina prvků jazyka zachází s náhradními páry jako se dvěma znaky. +Rovněž získání symbolu může být problematické, jelikož většina prvků jazyka zachází se zástupnými páry jako se dvěma znaky. Například zde vidíme na výstupu dva podivné znaky: ```js run alert( '𝒳'[0] ); // zobrazuje zvláštní symboly... -alert( '𝒳'[1] ); // ...části náhradního páru +alert( '𝒳'[1] ); // ...části zástupného páru ``` -Části náhradního páru nemají jedna bez druhé žádný význam. V uvedeném příkladu se tedy ve skutečnosti zobrazí nesmysly. +Části zástupného páru nemají jedna bez druhé žádný význam. V uvedeném příkladu se tedy ve skutečnosti zobrazí nesmysly. -Technicky lze náhradní páry detekovat podle jejich kódu: jestliže znak má kód v intervalu `0xd800..0xdbff`, pak je to první část náhradního páru. Další znak (druhá část) musí mít kód v intervalu `0xdc00..0xdfff`. Tyto intervaly jsou ve standardu exkluzívně rezervovány pro náhradní páry. +Technicky lze zástupné páry detekovat podle jejich kódu: jestliže znak má kód v intervalu `0xd800..0xdbff`, pak je to první část zástupného páru. Další znak (druhá část) musí mít kód v intervalu `0xdc00..0xdfff`. Tyto intervaly jsou ve standardu exkluzívně rezervovány pro zástupné páry. -Proto byly do JavaScriptu přidány metody [String.fromCodePoint](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/fromCodePoint) a [str.codePointAt](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/codePointAt), které si dokáží s náhradními páry poradit. +Proto byly do JavaScriptu přidány metody [String.fromCodePoint](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/fromCodePoint) a [řetězec.codePointAt](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/codePointAt), které si dokáží se zástupnými páry poradit. -Jsou v zásadě stejné jako [String.fromCharCode](mdn:js/String/fromCharCode) a [řetězec.charCodeAt](mdn:js/String/charCodeAt), ale s náhradními páry zacházejí správně. +Jsou v zásadě stejné jako [String.fromCharCode](mdn:js/String/fromCharCode) a [řetězec.charCodeAt](mdn:js/String/charCodeAt), ale se zástupnými páry zacházejí správně. Zde vidíme rozdíl: ```js run -// charCodeAt nezná náhradní páry, takže vydá kód pro 1. část 𝒳: - +// charCodeAt nezná zástupné páry, takže vydá kód pro 1. část: alert( '𝒳'.charCodeAt(0).toString(16) ); // d835 -// codePointAt zná náhradní páry -alert( '𝒳'.codePointAt(0).toString(16) ); // 1d4b3, přečte obě části náhradního páru +// codePointAt zná zástupné páry +alert( '𝒳'.codePointAt(0).toString(16) ); // 1d4b3, přečte obě části zástupného páru ``` -Při tom všem, načítáme-li od pozice 1 (a to je zde dosti nekorektní), pak obě vrátí jen 2. část páru: +Ovšem načítáme-li od pozice 1 (a to je zde dosti nekorektní), pak obě vrátí jen druhou část páru: ```js run alert( '𝒳'.charCodeAt(1).toString(16) ); // dcb3 @@ -99,7 +98,7 @@ alert( '𝒳'.codePointAt(1).toString(16) ); // dcb3 // nesmyslná 2. část páru ``` -Další způsoby, jak si s náhradními páry poradit, naleznete v kapitole . Pravděpodobně pro to existují i speciální knihovny, ale žádná není dostatečně známá na to, abychom ji tady doporučili. +Další způsoby, jak si se zástupnými páry poradit, naleznete v kapitole . Pravděpodobně pro to existují i speciální knihovny, ale žádná není dostatečně známá na to, abychom ji tady doporučili. ````warn header="Zásadní zjištění: dělení řetězců na libovolném místě je nebezpečné" Nemůžeme jen tak rozdělit řetězec na libovolné pozici, např. volat `řetězec.slice(0, 6)` a očekávat, že to bude platný řetězec, např.: @@ -108,20 +107,20 @@ Nemůžeme jen tak rozdělit řetězec na libovolné pozici, např. volat `řet alert( 'ahoj 😂'.slice(0, 6) ); // ahoj [?] ``` -Zde vidíme na výstupu nesmyslný znak (první polovinu náhradního páru úsměvu). +Zde vidíme na výstupu nesmyslný znak (první polovinu zástupného páru úsměvu). -Mějte to na paměti, jestliže zamýšlíte zodpovědně pracovat s náhradními páry. Nemusí to být velký problém, ale aspoň byste měli chápat, co se děje. +Mějte to na paměti, jestliže zamýšlíte zodpovědně pracovat se zástupnými páry. Nemusí to být velký problém, ale aspoň byste měli rozumět tomu, co se děje. ```` ## Diakritická znaménka a normalizace -V mnoha jazycích jsou symboly, které se skládají ze základního znaku a znaménka nad/pod ním. +Mnoho jazyků obsahuje symboly, které se skládají ze základního znaku a znaménka nad nebo pod ním. Například písmeno `a` může být základním znakem pro tyto znaky: `àáâäãåā`. Většina běžných „složených“ znaků má v tabulce Unicode svůj vlastní kód. Ne však všechny, protože možných kombinací je příliš mnoho. -Aby standard Unicode podporoval libovolné složeniny, umožňuje nám použít několik znaků Unicode: základní znak následovaný jedním nebo více znaky „znamének“, které jej „ozdobí“. +Abychom mohli používat libovolné složeniny, standard Unicode nám umožňuje použít několik znaků Unicode za sebou: základní znak následovaný jedním nebo více znaky „znamének“, která jej „ozdobí“. Například máme-li `S` následované speciálním znakem „tečka nahoře“ (kód `\u0307`), zobrazí se jako Ṡ. @@ -152,7 +151,7 @@ alert( `s1: ${s1}, s2: ${s2}` ); alert( s1 == s2 ); // false, třebaže znaky vypadají stejně (?!) ``` -K tomu, abychom to vyřešili, existuje algoritmus „normalizace Unicode“, který převádí každý řetězec do jednoduché „normální“ formy. +Řešení nám poskytuje algoritmus „normalizace Unicode“, který převádí každý řetězec do jednoduché „normální“ formy. Je implementován metodou [řetězec.normalize()](mdn:js/String/normalize). @@ -160,7 +159,7 @@ Je implementován metodou [řetězec.normalize()](mdn:js/String/normalize). alert( "S\u0307\u0323".normalize() == "S\u0323\u0307".normalize() ); // true ``` -Je humorné, že v naší situaci `normalize()` ve skutečnosti spojí posloupnost 3 znaků do jednoho: `\u1e68` (S se dvěma tečkami). +Je humorné, že v naší situaci `normalize()` ve skutečnosti spojí posloupnost tří znaků do jednoho: `\u1e68` (S se dvěma tečkami). ```js run alert( "S\u0307\u0323".normalize().length ); // 1 @@ -168,6 +167,6 @@ alert( "S\u0307\u0323".normalize().length ); // 1 alert( "S\u0307\u0323".normalize() == "\u1e68" ); // true ``` -V realitě však tomu tak není vždy. Důvod je, že symbol `Ṩ` je „dostatečně běžný“, takže jej tvůrci Unicode zahrnuli do hlavní tabulky a přiřadili mu kód. +V realitě však tomu tak není vždy. Důvodem je, že symbol `Ṩ` je „dostatečně běžný“, takže jej tvůrci Unicode zahrnuli do hlavní tabulky a přiřadili mu kód. -Pokud se chcete o pravidlech normalizace a variantách dozvědět víc -- jsou popsány v příloze standardu Unicode: [Normalizační formy Unicode](https://www.unicode.org/reports/tr15/), ale pro většinu praktických účelů je informace z tohoto článku dostačující. +Pokud se chcete o pravidlech a variantách normalizace dozvědět víc, jsou popsána v příloze standardu Unicode: [Normalizační formy Unicode](https://www.unicode.org/reports/tr15/), ale pro většinu praktických účelů je informace z tohoto článku dostačující. diff --git a/1-js/99-js-misc/07-weakref-finalizationregistry/article.md b/1-js/99-js-misc/07-weakref-finalizationregistry/article.md index 777bf703c..14cb0a5b7 100644 --- a/1-js/99-js-misc/07-weakref-finalizationregistry/article.md +++ b/1-js/99-js-misc/07-weakref-finalizationregistry/article.md @@ -1,483 +1,452 @@ -# WeakRef and FinalizationRegistry +# WeakRef a FinalizationRegistry -```warn header="\"Hidden\" features of the language" -This article covers a very narrowly focused topic, that most developers extremely rarely encounter in practice (and may not even be aware of its existence). +```warn header="„Skryté“ prvky jazyka" +Tento článek pokrývá velmi úzce zaměřené téma, s nímž se většina vývojářů v praxi setká jen velmi vzácně (a možná ani neví o jeho existenci). -We recommend skipping this chapter if you have just started learning JavaScript. +Pokud se JavaScript teprve začínáte učit, doporučujeme vám tuto kapitolu přeskočit. ``` -Recalling the basic concept of the *reachability principle* from the chapter, -we can note that the JavaScript engine is guaranteed to keep values in memory that are accessible or in use. +Vzpomeňme si na základní koncept *principu dosažitelnosti* z kapitoly a poznamenejme, že motor JavaScriptu zaručeně udrží v paměti hodnoty, které jsou dostupné nebo se používají. -For example: +Například: ```js -// the user variable holds a strong reference to the object -let user = { name: "John" }; +// proměnná uživatel obsahuje silný odkaz na objekt +let uživatel = { jméno: "Jan" }; -// let's overwrite the value of the user variable -user = null; +// přepíšeme hodnotu proměnné uživatel +uživatel = null; -// the reference is lost and the object will be deleted from memory +// odkaz je ztracen a objekt bude vymazán z paměti ``` -Or a similar, but slightly more complicated code with two strong references: +Nebo podobný, ale trošku složitější kód se dvěma silnými odkazy: ```js -// the user variable holds a strong reference to the object -let user = { name: "John" }; +// proměnná uživatel obsahuje silný odkaz na objekt +let uživatel = { jméno: "Jan" }; -// copied the strong reference to the object into the admin variable +// zkopírujeme silný odkaz na objekt do proměnné správce *!* -let admin = user; +let správce = uživatel; */!* -// let's overwrite the value of the user variable -user = null; +// přepíšeme hodnotu proměnné uživatel +uživatel = null; -// the object is still reachable through the admin variable +// objekt je stále dosažitelný z proměnné správce ``` -The object `{ name: "John" }` would only be deleted from memory if there were no strong references to it (if we also overwrote the value of the `admin` variable). +Objekt `{ jméno: "Jan" }` bude smazán z paměti teprve tehdy, až na něj nebudou existovat žádné silné odkazy (tedy až přepíšeme i hodnotu proměnné `správce`). -In JavaScript, there is a concept called `WeakRef`, which behaves slightly differently in this case. +V JavaScriptu existuje koncept nazývaný `WeakRef`, který se v tomto případě chová poněkud odlišně. -````smart header="Terms: \"Strong reference\", \"Weak reference\"" -**Strong reference** - is a reference to an object or value, that prevents them from being deleted by the garbage collector. Thereby, keeping the object or value in memory, to which it points. +````smart header="Pojmy: „silný odkaz“, „slabý odkaz“" +**Silný odkaz** - je odkaz na objekt nebo hodnotu, který zabraňuje jejich smazání sběračem odpadků. Udržuje tedy objekt nebo hodnotu v paměti, na níž ukazuje. -This means, that the object or value remains in memory and is not collected by the garbage collector as long, as there are active strong references to it. +To znamená, že objekt nebo hodnota zůstane v paměti a nebude odklizen sběračem odpadků, dokud na něj budou existovat aktivní silné odkazy. -In JavaScript, ordinary references to objects are strong references. For example: +Běžné odkazy na objekty v JavaScriptu jsou silné odkazy. Například: ```js -// the user variable holds a strong reference to this object -let user = { name: "John" }; +// proměnná uživatel obsahuje silný odkaz na objekt +let uživatel = { jméno: "Jan" }; ``` -**Weak reference** - is a reference to an object or value, that does *not* prevent them from being deleted by the garbage collector. -An object or value can be deleted by the garbage collector if, the only remaining references to them are weak references. +**Slabý odkaz** - je odkaz na objekt nebo hodnotu, který *nebrání* jejich smazání sběračem odpadků. +Objekt nebo hodnota může být smazán sběračem odpadků, jestliže všechny zbývající odkazy na něj jsou slabé. ```` ## WeakRef -````warn header="Note of caution" -Before we dive into it, it is worth noting that the correct use of the structures discussed in this article requires very careful thought, and they are best avoided if possible. +````warn header="Upozornění" +Než se do toho ponoříme, stojí za zmínku, že korektní používání struktur probíraných v tomto článku vyžaduje velmi opatrné přemýšlení a je lépe se jim vyhnout, pokud je to možné. ```` -`WeakRef` - is an object, that contains a weak reference to another object, called `target` or `referent`. +`WeakRef` - je objekt, který obsahuje slabý odkaz na jiný objekt, nazývaný `cíl` nebo `referent`. -The peculiarity of `WeakRef` is that it does not prevent the garbage collector from deleting its referent-object. In other words, a `WeakRef` object does not keep the `referent` object alive. +Zvláštnost `WeakRef` spočívá v tom, že nebrání sběrači odpadků v odstranění svého referovaného objektu. Jinými slovy, objekt `WeakRef` neponechává objekt `referent` naživu. -Now let's take the `user` variable as the "referent" and create a weak reference from it to the `admin` variable. -To create a weak reference, you need to use the `WeakRef` constructor, passing in the target object (the object you want a weak reference to). +Vezměme nyní jako referovaný objekt proměnnou `uživatel` a vytvořme na ni slabý odkaz z proměnné `správce`. +Abychom vytvořili slabý odkaz, musíme použít konstruktor třídy `WeakRef` a předat mu cílový objekt (objekt, na který chceme slabý odkaz vytvořit). -In our case — this is the `user` variable: +V našem případě to bude proměnná `uživatel`: ```js -// the user variable holds a strong reference to the object -let user = { name: "John" }; +// proměnná uživatel obsahuje silný odkaz na objekt +let uživatel = { jméno: "Jan" }; -// the admin variable holds a weak reference to the object +// proměnná správce obsahuje slabý odkaz na objekt *!* -let admin = new WeakRef(user); +let správce = new WeakRef(uživatel); */!* ``` -The diagram below depicts two types of references: a strong reference using the `user` variable and a weak reference using the `admin` variable: +Následující diagram zobrazuje dva druhy odkazů: silný odkaz pomocí proměnné `uživatel` a slabý odkaz pomocí proměnné `správce`: ![](weakref-finalizationregistry-01.svg) -Then, at some point, we stop using the `user` variable - it gets overwritten, goes out of scope, etc., while keeping the `WeakRef` instance in the `admin` variable: +Pak v určitém okamžiku přestaneme používat proměnnou `uživatel` - bude přepsána, opustí rozsah platnosti atd., zatímco instanci `WeakRef` v proměnné `správce` budeme udržovat: ```js -// let's overwrite the value of the user variable -user = null; +// přepíšeme hodnotu proměnné uživatel +uživatel = null; ``` -A weak reference to an object is not enough to keep it "alive". When the only remaining references to a referent-object are weak references, the garbage collector is free to destroy this object and use its memory for something else. +Slabý odkaz na objekt nestačí k jeho udržení „naživu“. Když budou všechny zbývající odkazy na referovaný objekt slabé, sběrač odpadků může tento objekt zničit a paměť, kterou objekt obsazoval, může být využita k něčemu jinému. -However, until the object is actually destroyed, the weak reference may return it, even if there are no more strong references to this object. -That is, our object becomes a kind of "[Schrödinger's cat](https://en.wikipedia.org/wiki/Schr%C3%B6dinger%27s_cat)" – we cannot know for sure whether it's "alive" or "dead": +Dokud však není objekt skutečně zničen, slabý odkaz jej může vracet, i když na něj už neexistují žádné silné odkazy. +Náš objekt se tedy stává něčím jako „[Schrödingerova kočka](https://cs.wikipedia.org/wiki/Schr%C3%B6dingerova_ko%C4%8Dka)“ – nemůžeme s jistotou vědět, zda je „živý“ nebo „mrtvý“: ![](weakref-finalizationregistry-02.svg) -At this point, to get the object from the `WeakRef` instance, we will use its `deref()` method. +Když v této chvíli chceme získat objekt z instance `WeakRef`, použijeme její metodu `deref()`. -The `deref()` method returns the referent-object that the `WeakRef` points to, if the object is still in memory. If the object has been deleted by the garbage collector, then the `deref()` method will return `undefined`: +Metoda `deref()` vrátí referovaný objekt, na který `WeakRef` ukazuje, pokud je tento objekt stále v paměti. Jestliže byl objekt smazán sběračem odpadků, pak metoda `deref()` vrátí `undefined`: ```js -let ref = admin.deref(); +let ref = správce.deref(); if (ref) { - // the object is still accessible: we can perform any manipulations with it + // objekt je stále dostupný: můžeme s ním provádět jakékoli manipulace } else { - // the object has been collected by the garbage collector + // objekt byl odklizen sběračem odpadků } ``` -## WeakRef use cases +## Případy použití WeakRef -`WeakRef` is typically used to create caches or [associative arrays](https://en.wikipedia.org/wiki/Associative_array) that store resource-intensive objects. -This allows one to avoid preventing these objects from being collected by the garbage collector solely based on their presence in the cache or associative array. +`WeakRef` se obvykle používá k vytváření mezipamětí (cache) nebo [asociativních polí](https://cs.wikipedia.org/wiki/Asociativn%C3%AD_pole), do nichž se ukládají objekty náročné na zdroje. +To nám umožňuje vyhnout se tomu, aby tyto objekty nemohly být odklizeny sběračem odpadků jen proto, že jsou uloženy v mezipaměti nebo asociativním poli. -One of the primary examples - is a situation when we have numerous binary image objects (for instance, represented as `ArrayBuffer` or `Blob`), and we want to associate a name or path with each image. -Existing data structures are not quite suitable for these purposes: +Jedním z primárních příkladů je situace, kdy máme větší množství objektů binárních obrázků (reprezentovaných například jako `ArrayBuffer` nebo `Blob`) a chceme ke každému z nich připojit název nebo cestu. +Existující datové struktury nejsou pro tento účel příliš vhodné: -- Using `Map` to create associations between names and images, or vice versa, will keep the image objects in memory since they are present in the `Map` as keys or values. -- `WeakMap` is ineligible for this goal either: because the objects represented as `WeakMap` keys use weak references, and are not protected from deletion by the garbage collector. +- Použijeme-li k vytvoření asociací mezi názvy a obrázky nebo opačně `Map`, objekty obrázků budou stále zůstávat v paměti, neboť se budou nacházet v `Map` jako klíče nebo hodnoty. +- Ani `WeakMap` se pro tento účel nehodí, protože objekty představované jako klíče `WeakMap` používají slabé odkazy a nejsou tedy chráněny před smazáním sběračem odpadků. -But, in this situation, we need a data structure that would use weak references in its values. +V této situaci však potřebujeme datovou strukturu, která by používala slabé odkazy ve svých hodnotách. -For this purpose, we can use a `Map` collection, whose values are `WeakRef` instances referring to the large objects we need. -Consequently, we will not keep these large and unnecessary objects in memory longer than they should be. +K tomuto účelu můžeme použít kolekci `Map`, jejíž hodnoty jsou instance `WeakRef`, které odkazují na potřebné velké objekty. +Důsledkem bude, že tyto velké a nepotřebné objekty nebudeme udržovat v paměti déle, než bychom měli. -Otherwise, this is a way to get the image object from the cache if it is still reachable. -If it has been garbage collected, we will re-generate or re-download it again. +Kromě toho to je způsob, jak získat z mezipaměti objekt obrázku, je-li stále dosažitelný. +Pokud již byl odstraněn sběračem odpadků, můžeme jej přegenerovat nebo stáhnout znovu. -This way, less memory is used in some situations. +Tímto způsobem v některým situacích spotřebujeme méně paměti. -## Example №1: using WeakRef for caching +## Příklad číslo 1: použití WeakRef pro mezipaměť -Below is a code snippet that demonstrates the technique of using `WeakRef`. +Následující úryvek kódu demonstruje techniku používání `WeakRef`. -In short, we use a `Map` with string keys and `WeakRef` objects as their values. -If the `WeakRef` object has not been collected by the garbage collector, we get it from the cache. -Otherwise, we re-download it again and put it in the cache for further possible reuse: +Zkráceně řečeno, použijeme `Map`, jejíž klíče budou řetězce a jejíž hodnoty budou objekty `WeakRef`. +Jestliže objekt ve `WeakRef` ještě nebyl odklizen sběračem odpadků, získáme jej z mezipaměti. +V opačném případě jej znovu stáhneme a uložíme do mezipaměti pro případné další znovupoužití: ```js -function fetchImg() { - // abstract function for downloading images... +function stáhniObrázek() { + // abstraktní funkce pro stahování obrázků... } -function weakRefCache(fetchImg) { // (1) - const imgCache = new Map(); // (2) +function najdiVMezipaměti(stáhniObrázek) { // (1) + const paměťObrázků = new Map(); // (2) - return (imgName) => { // (3) - const cachedImg = imgCache.get(imgName); // (4) + return (názevObrázku) => { // (3) + const obrázekVPaměti = paměťObrázků.get(názevObrázku); // (4) - if (cachedImg?.deref()) { // (5) - return cachedImg?.deref(); + if (obrázekVPaměti?.deref()) { // (5) + return obrázekVPaměti?.deref(); } - const newImg = fetchImg(imgName); // (6) - imgCache.set(imgName, new WeakRef(newImg)); // (7) + const novýObrázek = stáhniObrázek(názevObrázku); // (6) + paměťObrázků.set(názevObrázku, new WeakRef(novýObrázek)); // (7) - return newImg; + return novýObrázek; }; } -const getCachedImg = weakRefCache(fetchImg); +const vraťObrázekVPaměti = najdiVMezipaměti(stáhniObrázek); ``` -Let's delve into the details of what happened here: -1. `weakRefCache` - is a higher-order function that takes another function, `fetchImg`, as an argument. In this example, we can neglect a detailed description of the `fetchImg` function, since it can be any logic for downloading images. -2. `imgCache` - is a cache of images, that stores cached results of the `fetchImg` function, in the form of string keys (image name) and `WeakRef` objects as their values. -3. Return an anonymous function that takes the image name as an argument. This argument will be used as a key for the cached image. -4. Trying to get the cached result from the cache, using the provided key (image name). -5. If the cache contains a value for the specified key, and the `WeakRef` object has not been deleted by the garbage collector, return the cached result. -6. If there is no entry in the cache with the requested key, or `deref()` method returns `undefined` (meaning that the `WeakRef` object has been garbage collected), the `fetchImg` function downloads the image again. -7. Put the downloaded image into the cache as a `WeakRef` object. +Podívejme se podrobně, co se tady děje: +1. `najdiVMezipaměti` - je funkce vyššího řádu, která jako argument obdrží jinou funkci, `stáhniObrázek`. V tomto příkladu můžeme podrobný popis funkce `stáhniObrázek` vynechat, jelikož to může být jakákoli logika stahování obrázků. +2. `paměťObrázků` - je úložiště obrázků, do něhož se ukládají výsledky funkce `stáhniObrázek` ve formě řetězcových klíčů (název obrázku) a objektů třídy `WeakRef` jako hodnot. +3. Vrátíme anonymní funkci, jejímž argumentem je název obrázku. Tento argument bude použit jako klíč pro uložený obrázek. +4. Snažíme se získat uložený výsledek z úložiště podle zadaného klíče (název obrázku). +5. Jestliže úložiště obsahuje pro zadaný klíč nějakou hodnotu a objekt `WeakRef` nebyl odklizen sběračem odpadků, vrátíme uložený výsledek. +6. Jestliže pro požadovaný klíč neexistuje v úložišti žádný záznam nebo metoda `deref()` vrátí `undefined` (což znamená, že objekt `WeakRef` byl odklizen sběračem odpadků), funkce `stáhniObrázek` stáhne obrázek znovu. +7. Stažený obrázek uložíme do úložiště jako objekt `WeakRef`. -Now we have a `Map` collection, where the keys - are image names as strings, and values - are `WeakRef` objects containing the images themselves. +Nyní máme kolekci `Map`, jejíž klíče jsou řetězce s názvy obrázků a jejíž hodnoty jsou objekty `WeakRef` obsahující samotné obrázky. -This technique helps to avoid allocating a large amount of memory for resource-intensive objects, that nobody uses anymore. -It also saves memory and time in case of reusing cached objects. +Tato technika nám pomůže vyhnout se zabírání velkého množství paměti pro objekty náročné na zdroje, které již nikdo nepoužívá. +Rovněž šetří paměť a čas v případě opakovaného použití uložených objektů. -Here is a visual representation of what this code looks like: +Následuje vizuální reprezentace toho, jak tento kód vypadá: ![](weakref-finalizationregistry-03.svg) -But, this implementation has its drawbacks: over time, `Map` will be filled with strings as keys, that point to a `WeakRef`, whose referent-object has already been garbage collected: +Tato implementace však má své nevýhody: po čase bude `Map` plná řetězcových klíčů, které ukazují na `WeakRef`, jejichž referovaný objekt již byl odstraněn sběračem: ![](weakref-finalizationregistry-04.svg) -One way to handle this problem - is to periodically scavenge the cache and clear out "dead" entries. -Another way - is to use finalizers, which we will explore next. +Jedním způsobem, jak tento problém vyřešit, je pravidelně procházet úložiště a odstraňovat „mrtvé“ záznamy. +Dalším způsobem je použít finalizátory, které prozkoumáme později. -## Example №2: Using WeakRef to track DOM objects +## Příklad číslo 2: použití WeakRef ke sledování DOM objektů -Another use case for `WeakRef` - is tracking DOM objects. +Dalším případem použití `WeakRef` je sledování DOM objektů. -Let's imagine a scenario where some third-party code or library interacts with elements on our page as long as they exist in the DOM. -For example, it could be an external utility for monitoring and notifying about the system's state (commonly so-called "logger" – a program that sends informational messages called "logs"). +Představme si scénář, v němž kód nebo knihovna třetí strany pracuje s elementy na naší stránce tak dlouho, dokud existují v DOMu. Může to být například externí utilita pro monitorování a oznamování stavu systému (běžně nazývaná „logger“ – program, který posílá informační zprávy nazývané „logy“). -Interactive example: +Interaktivní příklad: [codetabs height=420 src="weakref-dom"] -When the "Start sending messages" button is clicked, in the so-called "logs display window" (an element with the `.window__body` class), messages (logs) start to appear. +Když kliknete na tlačítko „Začít posílat zprávy“, začnou se objevovat zprávy (logy) v tzv. „okně zobrazování zpráv“ (element třídy `.window__body`). -But, as soon as this element is deleted from the DOM, the logger should stop sending messages. -To reproduce the removal of this element, just click the "Close" button in the top right corner. +Jakmile je však tento element z DOMu smazán, logger by měl přestat zprávy zasílat. Abyste odstranění tohoto elementu reprodukovali, stačí kliknout na tlačítko „Zavřít“ v pravém horním rohu. -In order not to complicate our work, and not to notify third-party code every time our DOM-element is available, and when it is not, it will be enough to create a weak reference to it using `WeakRef`. +Abychom si nekomplikovali práci a neposílali oznámení kódu třetí strany pokaždé, když je a když není náš DOM element k dispozici, postačí na něj vytvořit slabý odkaz pomocí `WeakRef`. -Once the element is removed from the DOM, the logger will notice it and stop sending messages. +Když bude element odstraněn z DOMu, logger si toho všimne a přestane zprávy posílat. -Now let's take a closer look at the source code (*tab `index.js`*): +Nyní se blíže podívejme na zdrojový kód (*záložka `index.js`*): -1. Get the DOM-element of the "Start sending messages" button. -2. Get the DOM-element of the "Close" button. -3. Get the DOM-element of the logs display window using the `new WeakRef()` constructor. This way, the `windowElementRef` variable holds a weak reference to the DOM-element. -4. Add an event listener on the "Start sending messages" button, responsible for starting the logger when clicked. -5. Add an event listener on the "Close" button, responsible for closing the logs display window when clicked. -6. Use `setInterval` to start displaying a new message every second. -7. If the DOM-element of the logs display window is still accessible and kept in memory, create and send a new message. -8. If the `deref()` method returns `undefined`, it means that the DOM-element has been deleted from memory. In this case, the logger stops displaying messages and clears the timer. -9. `alert`, which will be called, after the DOM-element of the logs display window is deleted from memory (i.e. after clicking the "Close" button). **Note, that deletion from memory may not happen immediately, as it depends only on the internal mechanisms of the garbage collector.** +1. Získáme DOM element tlačítka „Začít posílat zprávy“. +2. Získáme DOM element tlačítka „Zavřít“. +3. Získáme DOM element okna zobrazení logů pomocí konstruktoru `new WeakRef()`. Pak bude proměnná `odkazNaElementOkna` obsahovat slabý odkaz na tento DOM element. +4. Přidáme k tlačítku „Začít posílat zprávy“ posluchače událostí, který bude zajišťovat rozběhnutí loggeru po kliknutí na tlačítko. +5. Přidáme k tlačítku „Zavřít“ posluchače událostí, který bude zajišťovat zavření okna s logy po kliknutí na tlačítko. +6. Pomocí `setInterval` začneme každou sekundu zobrazovat zprávu. +7. Jestliže je DOM element okna zobrazujícího zprávy stále dostupný a udržovaný v paměti, vytvoříme a pošleme novou zprávu. +8. Jestliže metoda `deref()` vrátí `undefined`, znamená to, že DOM element byl odstraněn z paměti. V tom případě logger přestane zobrazovat zprávy a zruší časovač. +9. Tento `alert` bude volán poté, co bude DOM element okna zobrazování zpráv odstraněn z paměti (tj. po kliknutí na tlačítko „Zavřít“). **Všimněte si, že k odstranění z paměti nemusí dojít okamžitě. Závisí to výhradně na vnitřních mechanismech sběrače odpadků.** - We cannot control this process directly from the code. However, despite this, we still have the option to force garbage collection from the browser. - - In Google Chrome, for example, to do this, you need to open the developer tools (`key:Ctrl` + `key:Shift` + `key:J` on Windows/Linux or `key:Option` + `key:⌘` + `key:J` on macOS), go to the "Performance" tab, and click on the bin icon button – "Collect garbage": + Tento proces nemůžeme ovládat přímo z kódu. Přesto však máme možnost vynutit si spuštění sběru odpadků z prohlížeče. + + Například v Google Chrome to provedeme tak, že otevřeme vývojářské nástroje (`key:Ctrl` + `key:Shift` + `key:J` ve Windows/Linuxu nebo `key:Option` + `key:⌘` + `key:J` v macOS), přejdeme na záložku „Výkon“ („Performance“) a klikneme na ikonu odpadkového koše -- „Uvolnění paměti“ („Collect garbage“): ![](google-chrome-developer-tools.png)
- This functionality is supported in most modern browsers. After the actions are taken, the alert will trigger immediately. + Tuto funkcionalitu podporuje většina moderních prohlížečů. Po provedení těchto akcí se okamžitě spustí alert. ## FinalizationRegistry -Now it is time to talk about finalizers. Before we move on, let's clarify the terminology: +Nyní nastal čas pohovořit o finalizátorech. Než budeme pokračovat, ujasníme si terminologii: -**Cleanup callback (finalizer)** - is a function that is executed, when an object, registered in the `FinalizationRegistry`, is deleted from memory by the garbage collector. +**Úklidový callback (finalizátor)** - je funkce, která je spuštěna, když je objekt registrovaný ve `FinalizationRegistry` odstraněn z paměti sběračem odpadků. -Its purpose - is to provide the ability to perform additional operations, related to the object, after it has been finally deleted from memory. +Jejím účelem je poskytnout možnost provést další operace vztahující se k objektu poté, co byl definitivně odstraněn z paměti. -**Registry** (or `FinalizationRegistry`) - is a special object in JavaScript that manages the registration and unregistration of objects and their cleanup callbacks. +**Registr** (nebo `FinalizationRegistry`) - je speciální objekt v JavaScriptu, který spravuje registraci a deregistraci objektů a jejich úklidových callbacků. -This mechanism allows registering an object to track and associate a cleanup callback with it. -Essentially it is a structure that stores information about registered objects and their cleanup callbacks, and then automatically invokes those callbacks when the objects are deleted from memory. +Tento mechanismus umožňuje registrovat objekt ke sledování a připojit k němu úklidový callback. +V zásadě je to struktura, která ukládá informace o registrovaných objektech a jejich úklidových callbaccích a pak, když jsou objekty odstraněny z paměti, tyto callbacky automaticky vyvolává. -To create an instance of the `FinalizationRegistry`, it needs to call its constructor, which takes a single argument - the cleanup callback (finalizer). +Abychom vytvořili instanci třídy `FinalizationRegistry`, musíme volat její konstruktor, který obsahuje jediný argument - úklidový callback (finalizátor). -Syntax: +Syntaxe: ```js -function cleanupCallback(heldValue) { - // cleanup callback code +function úklidovýCallback(uchovávanáHodnota) { + // kód úklidového callbacku } -const registry = new FinalizationRegistry(cleanupCallback); +const registr = new FinalizationRegistry(úklidovýCallback); ``` -Here: - -- `cleanupCallback` - a cleanup callback that will be automatically called when a registered object is deleted from memory. -- `heldValue` - the value that is passed as an argument to the cleanup callback. If `heldValue` is an object, the registry keeps a strong reference to it. -- `registry` - an instance of `FinalizationRegistry`. +Zde: -`FinalizationRegistry` methods: +- `úklidovýCallback` - úklidový callback, který bude automaticky zavolán, až bude registrovaný objekt odstraněn z paměti. +- `uchovávanáHodnota` - hodnota, která je předána úklidovému callbacku jako argument. Pokud `uchovávanáHodnota` je objekt, registr si na něj uchovává silný odkaz. +- `registr` - instance třídy `FinalizationRegistry`. -- `register(target, heldValue [, unregisterToken])` - used to register objects in the registry. +Metody třídy `FinalizationRegistry`: - `target` - the object being registered for tracking. If the `target` is garbage collected, the cleanup callback will be called with `heldValue` as its argument. +- `register(cíl, uchovávanáHodnota [, registračníZnámka])` - používá se k registraci objektů v registru. - Optional `unregisterToken` – an unregistration token. It can be passed to unregister an object before the garbage collector deletes it. Typically, the `target` object is used as `unregisterToken`, which is the standard practice. -- `unregister(unregisterToken)` - the `unregister` method is used to unregister an object from the registry. It takes one argument - `unregisterToken` (the unregister token that was obtained when registering the object). + `cíl` - objekt registrovaný pro sledování. Pokud je `cíl` odstraněn sběračem odpadků, bude zavolán úklidový callback s argumentem `uchovávanáHodnota`. + + Nepovinná `registračníZnámka` – známka pro zrušení registrace. Můžeme ji předat, abychom mohli registraci objektu zrušit ještě dříve, než jej sběrač odpadků odstraní. Zpravidla se jako `registračníZnámka` používá objekt `cíl`, což je standardní praktika. +- `unregister(registračníZnámka)` - metoda `unregister` se používá ke zrušení registrace objektu v registru. Obsahuje jeden argument - `registračníZnámka` (známka pro zrušení registrace, která byla zadána při registraci objektu). -Now let's move on to a simple example. Let's use the already-known `user` object and create an instance of `FinalizationRegistry`: +Přejděme nyní k jednoduchému příkladu. Využijme již známý objekt `uživatel` a vytvořme instanci třídy `FinalizationRegistry`: ```js -let user = { name: "John" }; +let uživatel = { jméno: "Jan" }; -const registry = new FinalizationRegistry((heldValue) => { - console.log(`${heldValue} has been collected by the garbage collector.`); +const registr = new FinalizationRegistry((uchovávanáHodnota) => { + console.log(`${uchovávanáHodnota} byl odstraněn sběračem odpadků.`); }); ``` -Then, we will register the object, that requires a cleanup callback by calling the `register` method: +Pak objekt, pro který požadujeme úklidový callback, zaregistrujeme voláním metody `register`: ```js -registry.register(user, user.name); +registr.register(uživatel, uživatel.jméno); ``` -The registry does not keep a strong reference to the object being registered, as this would defeat its purpose. If the registry kept a strong reference, then the object would never be garbage collected. +Registr si na registrovaný objekt neuchovává silný odkaz, protože by tím ztratil smysl. Kdyby si jej uchovával, objekt by nikdy nebyl sběračem odpadků odklizen. -If the object is deleted by the garbage collector, our cleanup callback may be called at some point in the future, with the `heldValue` passed to it: +Jestliže objekt bude odklizen sběračem odpadků, může být někdy v budoucnu zavolán náš úklidový callback, kterému se předá `uchovávanáHodnota`: ```js -// When the user object is deleted by the garbage collector, the following message will be printed in the console: -"John has been collected by the garbage collector." +// Když je objekt uživatel odklizen sběračem odpadků, vypíše se na konzoli následující zpráva: +"Jan byl odstraněn sběračem odpadků." ``` -There are also situations where, even in implementations that use a cleanup callback, there is a chance that it will not be called. +Existují však situace, v nichž se i v implementacích využívajících úklidový callback může stát, že úklidový callback nebude nikdy zavolán. -For example: -- When the program fully terminates its operation (for example, when closing a tab in a browser). -- When the `FinalizationRegistry` instance itself is no longer reachable to JavaScript code. - If the object that creates the `FinalizationRegistry` instance goes out of scope or is deleted, the cleanup callbacks registered in that registry might also not be invoked. +Například: +- Když běh programu zcela skončí (např. při zavření záložky v prohlížeči). +- Když se samotná instance `FinalizationRegistry` stane nedosažitelnou z JavaScriptového kódu. + Jestliže objekt, který vytvořil instanci třídy `FinalizationRegistry`, opustí rozsah platnosti nebo bude smazán, úklidové callbacky registrované v tomto registru nemusejí být vyvolány. -## Caching with FinalizationRegistry +## Ukládání do mezipaměti pomocí FinalizationRegistry -Returning to our *weak* cache example, we can notice the following: -- Even though the values wrapped in the `WeakRef` have been collected by the garbage collector, there is still an issue of "memory leakage" in the form of the remaining keys, whose values have been collected by the garbage collector. +Když se vrátíme k našemu příkladu *slabé* mezipaměti, můžeme si všimnout následujícího: +- I když byly hodnoty zabalené do `WeakRef` odklizeny sběračem odpadků, stále je tady problém s „únikem paměti“ v podobě zbývajících klíčů, jejichž hodnoty sběrač odpadků odstranil. -Here is an improved caching example using `FinalizationRegistry`: +Následuje vylepšený příklad mezipaměti s využitím `FinalizationRegistry`: ```js -function fetchImg() { - // abstract function for downloading images... +function stáhniObrázek() { + // abstraktní funkce pro načítání obrázků... } -function weakRefCache(fetchImg) { - const imgCache = new Map(); +function najdiVMezipaměti(stáhniObrázek) { + const paměťObrázků = new Map(); *!* - const registry = new FinalizationRegistry((imgName) => { // (1) - const cachedImg = imgCache.get(imgName); - if (cachedImg && !cachedImg.deref()) imgCache.delete(imgName); + const registr = new FinalizationRegistry((názevObrázku) => { // (1) + const obrázekVPaměti = paměťObrázků.get(názevObrázku); + if (obrázekVPaměti && !obrázekVPaměti.deref()) paměťObrázků.delete(názevObrázku); }); */!* - return (imgName) => { - const cachedImg = imgCache.get(imgName); + return (názevObrázku) => { + const obrázekVPaměti = paměťObrázků.get(názevObrázku); - if (cachedImg?.deref()) { - return cachedImg?.deref(); + if (obrázekVPaměti?.deref()) { + return obrázekVPaměti?.deref(); } - const newImg = fetchImg(imgName); - imgCache.set(imgName, new WeakRef(newImg)); + const novýObrázek = stáhniObrázek(názevObrázku); + paměťObrázků.set(názevObrázku, new WeakRef(novýObrázek)); *!* - registry.register(newImg, imgName); // (2) + registr.register(novýObrázek, názevObrázku); // (2) */!* - return newImg; + return novýObrázek; }; } -const getCachedImg = weakRefCache(fetchImg); +const vraťObrázekVPaměti = najdiVMezipaměti(stáhniObrázek); ``` -1. To manage the cleanup of "dead" cache entries, when the associated `WeakRef` objects are collected by the garbage collector, we create a `FinalizationRegistry` cleanup registry. +1. Abychom zajistili úklid „mrtvých“ záznamů v mezipaměti, když jsou připojené objekty ve `WeakRef` odklizeny sběračem odpadků, vytvoříme úklidový registr `FinalizationRegistry`. - The important point here is, that in the cleanup callback, it should be checked, if the entry was deleted by the garbage collector and not re-added, in order not to delete a "live" entry. -2. Once the new value (image) is downloaded and put into the cache, we register it in the finalizer registry to track the `WeakRef` object. + Důležitým bodem zde je, že v úklidovém callbacku bychom měli ověřovat, zda záznam byl odstraněn sběračem odpadků a nebyl znovu přidán, abychom nesmazali „živý“ záznam. +2. Když je stažena a umístěna do mezipaměti nová hodnota (obrázek), zaregistrujeme ji v registru finalizátorů, abychom mohli sledovat objekt `WeakRef`. -This implementation contains only actual or "live" key/value pairs. -In this case, each `WeakRef` object is registered in the `FinalizationRegistry`. -And after the objects are cleaned up by the garbage collector, the cleanup callback will delete all `undefined` values. +Tato implementace obsahuje pouze aktuální neboli „živé“ dvojice klíč/hodnota. V tomto případě je každý objekt `WeakRef` zaregistrován ve `FinalizationRegistry` a poté, co jsou objekty odstraněny sběračem odpadků, úklidový callback smaže všechny hodnoty `undefined`. -Here is a visual representation of the updated code: +Na obrázku je vizuální reprezentace vylepšeného kódu: ![](weakref-finalizationregistry-05.svg) -A key aspect of the updated implementation is that finalizers allow parallel processes to be created between the "main" program and cleanup callbacks. -In the context of JavaScript, the "main" program - is our JavaScript-code, that runs and executes in our application or web page. +Klíčovým aspektem vylepšené implementace je, že finalizátory umožňují vytváření paralelních procesů mezi „hlavním“ programem a úklidovými callbacky. V kontextu JavaScriptu je „hlavním“ programem náš JavaScriptový kód, který je spuštěn a běží v naší aplikaci nebo webové stránce. -Hence, from the moment an object is marked for deletion by the garbage collector, and to the actual execution of the cleanup callback, there may be a certain time gap. -It is important to understand that during this time gap, the main program can make any changes to the object or even bring it back to memory. +Proto může mezi okamžikem, kdy je objekt označen ke smazání sběračem odpadků, a skutečným spuštěním úklidového callbacku nastat určitá časová prodleva. Je důležité pochopit, že během této prodlevy může hlavní program provést v objektu jakékoli změny nebo jej dokonce vrátit zpět do paměti. -That's why, in the cleanup callback, we must check to see if an entry has been added back to the cache by the main program to avoid deleting "live" entries. -Similarly, when searching for a key in the cache, there is a chance that the value has been deleted by the garbage collector, but the cleanup callback has not been executed yet. +Z tohoto důvodu musíme v úklidovém callbacku ověřovat, zda hlavní program nepřidal záznam zpět do mezipaměti, abychom se vyhnuli mazání „živých“ záznamů. Obdobně když v mezipaměti hledáme klíč, je možné, že jeho hodnota byla vymazána sběračem odpadků, ale úklidový callback ještě nebyl spuštěn. -Such situations require special attention if you are working with `FinalizationRegistry`. +Takové situace vyžadují při práci s `FinalizationRegistry` zvláštní pozornost. -## Using WeakRef and FinalizationRegistry in practice +## Použití WeakRef a FinalizationRegistry v praxi -Moving from theory to practice, imagine a real-life scenario, where a user synchronizes their photos on a mobile device with some cloud service -(such as [iCloud](https://en.wikipedia.org/wiki/ICloud) or [Google Photos](https://en.wikipedia.org/wiki/Google_Photos)), -and wants to view them from other devices. In addition to the basic functionality of viewing photos, such services offer a lot of additional features, for example: +Přejděme od teorie k praxi. Představte si scénář ze skutečného života, kdy si uživatel synchronizuje své fotografie na mobilním zařízení s nějakou cloudovou službou (např. [iCloud](https://cs.wikipedia.org/wiki/ICloud) nebo [Fotky Google](https://cs.wikipedia.org/wiki/Fotky_Google)) a chce si je prohlížet z jiných zařízení. Takové služby nabízejí kromě základní functionality prohlížení fotografií řadu dalších funkcí, například: -- Photo editing and video effects. -- Creating "memories" and albums. -- Video montage from a series of photos. -- ...and much more. +- Editaci fotografií a videoefektů. +- Vytváření „vzpomínek“ a alb. +- Montáž videa ze série fotografií. +- ...a mnoho dalšího. -Here, as an example, we will use a fairly primitive implementation of such a service. -The main point - is to show a possible scenario of using `WeakRef` and `FinalizationRegistry` together in real life. +Jako příklad zde uvedeme poměrně primitivní implementaci takové služby. Hlavním smyslem je ukázat možný scénář společného použití `WeakRef` a `FinalizationRegistry` ve skutečném životě. -Here is what it looks like: +Bude to vypadat následovně: ![](weakref-finalizationregistry-demo-01.png)
-On the left side, there is a cloud library of photos (they are displayed as thumbnails). -We can select the images we need and create a collage, by clicking the "Create collage" button on the right side of the page. -Then, the resulting collage can be downloaded as an image. +Na levé straně je cloudová knihovna fotografií (jsou zobrazeny jako náhledy). Můžeme si zvolit obrázky, jaké chceme, a kliknutím na tlačítko „Vytvořit koláž“ na pravé straně stránky z nich vytvořit koláž. Výslednou koláž si pak můžeme stáhnout jako obrázek.

-To increase page loading speed, it would be reasonable to download and display photo thumbnails in *compressed* quality. -But, to create a collage from selected photos, download and use them in *full-size* quality. +Abychom zvýšili rychlost načítání stránky, bude rozumné stahovat a zobrazovat náhledy fotografií v *komprimované* kvalitě. Když však ze zvolených fotografií budeme vytvářet koláž, stáhneme a použijeme je v *plné* kvalitě. -Below, we can see, that the intrinsic size of the thumbnails is 240x240 pixels. -The size was chosen on purpose to increase loading speed. -Moreover, we do not need full-size photos in preview mode. +Níže vidíme, že vnitřní velikost náhledů je 240x240 pixelů. Tuto velikost jsme zvolili, abychom zvýšili rychlost nahrávání. Navíc v režimu prohlížení nepotřebujeme fotografie v plné velikosti. ![](weakref-finalizationregistry-demo-02.png)
-Let's assume, that we need to create a collage of 4 photos: we select them, and then click the "Create collage" button. -At this stage, the already known to us weakRefCache function checks whether the required image is in the cache. -If not, it downloads it from the cloud and puts it in the cache for further use. -This happens for each selected image: +Předpokládejme, že potřebujeme vytvořit koláž čtyř fotografií: vybereme si je a pak klikneme na tlačítko „Vytvořit koláž“. V tuto chvíli funkce najdiVMezipaměti, kterou už známe, ověří, zda je požadovaný obrázek v mezipaměti. Pokud ne, stáhne jej z cloudu a uloží jej do mezipaměti pro další použití. To se bude odehrávat pro každý zvolený obrázek:

![](weakref-finalizationregistry-demo-03.gif)
-Paying attention to the output in the console, you can see, which of the photos were downloaded from the cloud - this is indicated by FETCHED_IMAGE. -Since this is the first attempt to create a collage, this means, that at this stage the "weak cache" was still empty, and all the photos were downloaded from the cloud and put in it. +Když budete sledovat výstup na konzoli, uvidíte, které z fotografií byly staženy z cloudu - ty jsou označeny jako STAŽENÝ_OBRÁZEK (FETCHED_IMAGE). Protože to je první pokus o vytvoření koláže, znamená to, že v této chvíli je „slabá mezipaměť“ ještě prázdná, a tak všechny fotografie budou staženy z cloudu a uloženy do ní. -But, along with the process of downloading images, there is also a process of memory cleanup by the garbage collector. -This means, that the object stored in the cache, which we refer to, using a weak reference, is deleted by the garbage collector. -And our finalizer executes successfully, thereby deleting the key, by which the image was stored in the cache. -CLEANED_IMAGE notifies us about it: +Společně s procesem stahování obrázků je zde však také proces čištění paměti sběračem odpadků. To znamená, že objekt uložený v mezipaměti, na který se odkazujeme slabým odkazem, je smazán sběračem odpadků. A náš finalizátor se úspěšně spustí a tím smaže klíč, pod nímž byl obrázek uložen v mezipaměti. Oznamuje nám to SMAZANÝ_OBRÁZEK (DELETED_IMAGE): ![](weakref-finalizationregistry-demo-04.jpg)
-Next, we realize that we do not like the resulting collage, and decide to change one of the images and create a new one. -To do this, just deselect the unnecessary image, select another one, and click the "Create collage" button again: +Pak zjistíme, že se nám výsledná koláž nelíbí, a rozhodneme se jeden obrázek změnit a vytvořit novou. To uděláme jednoduše tak, že smažeme nechtěný obrázek, vybereme jiný a opět klikneme na tlačítko „Vytvořit koláž“:

![](weakref-finalizationregistry-demo-05.gif)
-But this time not all images were downloaded from the network, and one of them was taken from the weak cache: the CACHED_IMAGE message tells us about it. -This means that at the time of collage creation, the garbage collector had not yet deleted our image, and we boldly took it from the cache, -thereby reducing the number of network requests and speeding up the overall time of the collage creation process: +Tentokrát však všechny obrázky nebyly staženy ze sítě, ale jeden z nich byl převzat ze slabé mezipaměti: o tom nám říká zpráva OBRÁZEK_Z_PAMĚTI (CACHED_IMAGE). To znamená, že v okamžiku vytvoření koláže sběrač odpadků náš obrázek ještě nesmazal a my jsme ho jen vytáhli z mezipaměti, čímž jsme snížili počet síťových požadavků a urychlili celkovou dobu procesu vytváření obrázků:

![](weakref-finalizationregistry-demo-06.jpg)
-Let's "play around" a little more, by replacing one of the images again and creating a new collage: +„Pohrajme si“ ještě dál. Znovu nahraďme jeden z obrázků jiným a vytvořme novou koláž:

![](weakref-finalizationregistry-demo-07.gif)
-This time the result is even more impressive. Of the 4 images selected, 3 of them were taken from the weak cache, and only one had to be downloaded from the network. -The reduction in network load was about 75%. Impressive, isn't it? +Výsledek je tentokrát ještě působivější. Ze čtyř zvolených obrázků byly tři vytaženy ze slabé mezipaměti a pouze jeden musel být stažen ze sítě. Síťová zátěž byla snížena zhruba o 75%. Úžasné, ne?

![](weakref-finalizationregistry-demo-08.jpg)
-Of course, it is important to remember, that such behavior is not guaranteed, and depends on the specific implementation and operation of the garbage collector. +Je samozřejmě důležité mít na paměti, že takové chování není zaručeno a závisí na specifické implementaci a operacích sběrače odpadků. -Based on this, a completely logical question immediately arises: why do not we use an ordinary cache, where we can manage its entities ourselves, instead of relying on the garbage collector? -That's right, in the vast majority of cases there is no need to use `WeakRef` and `FinalizationRegistry`. +Při tom okamžitě vyvstává zcela logická otázka: proč se spoléháme na sběrač odpadků a nepoužijeme místo toho obyčejnou mezipaměť, v níž bychom mohli záznamy spravovat sami? Je to pravda, v naprosté většině případů není potřeba `WeakRef` a `FinalizationRegistry` používat. -Here, we simply demonstrated an alternative implementation of similar functionality, using a non-trivial approach with interesting language features. -Still, we cannot rely on this example, if we need a constant and predictable result. +Zde jsme jednoduše předvedli alternativní implementaci podobné functionality použitím netriviálního přístupu se zajímavými vlastnostmi jazyka. Stále se však na tento příklad nemůžeme spolehnout, potřebujeme-li stabilní a předvídatelný výsledek. -You can [open this example in the sandbox](sandbox:weakref-finalizationregistry). +Tento příklad si můžete [otevřít na pískovišti](sandbox:weakref-finalizationregistry). -## Summary +## Shrnutí -`WeakRef` - designed to create weak references to objects, allowing them to be deleted from memory by the garbage collector if there are no longer strong references to them. -This is beneficial for addressing excessive memory usage and optimizing the utilization of system resources in applications. +`WeakRef` - byla navržena pro vytváření slabých odkazů na objekty a umožňuje jejich smazání z paměti sběračem odpadků, pokud na ně už neexistují žádné silné odkazy. To se vyplatí pro adresování rozsáhlého využití paměti a optimalizaci využití systémových zdrojů v aplikacích. -`FinalizationRegistry` - is a tool for registering callbacks, that are executed when objects that are no longer strongly referenced, are destroyed. -This allows releasing resources associated with the object or performing other necessary operations before deleting the object from memory. \ No newline at end of file +`FinalizationRegistry` - je nástroj pro registraci callbacků, které budou spuštěny při smazání objektů, na které již neexistují žádné silné odkazy. To nám umožňuje uvolnit zdroje spojené s těmito objekty nebo provést jiné nezbytné operace, než bude objekt z paměti odklizen. \ No newline at end of file diff --git a/1-js/99-js-misc/07-weakref-finalizationregistry/weakref-dom.view/index.html b/1-js/99-js-misc/07-weakref-finalizationregistry/weakref-dom.view/index.html index 7f93af4c7..088156522 100644 --- a/1-js/99-js-misc/07-weakref-finalizationregistry/weakref-dom.view/index.html +++ b/1-js/99-js-misc/07-weakref-finalizationregistry/weakref-dom.view/index.html @@ -10,14 +10,14 @@
- +
-

Messages:

- +

Zprávy:

+
- No messages. + Žádné zprávy.
diff --git a/1-js/99-js-misc/07-weakref-finalizationregistry/weakref-dom.view/index.js b/1-js/99-js-misc/07-weakref-finalizationregistry/weakref-dom.view/index.js index ea55b4478..72f8296dc 100644 --- a/1-js/99-js-misc/07-weakref-finalizationregistry/weakref-dom.view/index.js +++ b/1-js/99-js-misc/07-weakref-finalizationregistry/weakref-dom.view/index.js @@ -1,24 +1,24 @@ -const startMessagesBtn = document.querySelector('.start-messages'); // (1) -const closeWindowBtn = document.querySelector('.window__button'); // (2) -const windowElementRef = new WeakRef(document.querySelector(".window__body")); // (3) +const tlačítkoZačítPosílat = document.querySelector('.start-messages'); // (1) +const tlačítkoZavřítOkno = document.querySelector('.window__button'); // (2) +const odkazNaElementOkna = new WeakRef(document.querySelector(".window__body")); // (3) -startMessagesBtn.addEventListener('click', () => { // (4) - startMessages(windowElementRef); - startMessagesBtn.disabled = true; +tlačítkoZačítPosílat.addEventListener('click', () => { // (4) + startMessages(odkazNaElementOkna); + tlačítkoZačítPosílat.disabled = true; }); -closeWindowBtn.addEventListener('click', () => document.querySelector(".window__body").remove()); // (5) +tlačítkoZavřítOkno.addEventListener('click', () => document.querySelector(".window__body").remove()); // (5) -const startMessages = (element) => { - const timerId = setInterval(() => { // (6) +const začniPosílatZprávy = (element) => { + const idČasovače = setInterval(() => { // (6) if (element.deref()) { // (7) - const payload = document.createElement("p"); - payload.textContent = `Message: System status OK: ${new Date().toLocaleTimeString()}`; - element.deref().append(payload); + const zátěž = document.createElement("p"); + zátěž.textContent = `Zpráva: Stav systému OK: ${new Date().toLocaleTimeString()}`; + element.deref().append(zátěž); } else { // (8) - alert("The element has been deleted."); // (9) - clearInterval(timerId); + alert("Element byl odstraněn."); // (9) + clearInterval(idČasovače); } }, 1000); }; \ No newline at end of file diff --git a/1-js/99-js-misc/07-weakref-finalizationregistry/weakref-finalizationregistry-01.svg b/1-js/99-js-misc/07-weakref-finalizationregistry/weakref-finalizationregistry-01.svg index 2a507dbcd..1f76262e5 100644 --- a/1-js/99-js-misc/07-weakref-finalizationregistry/weakref-finalizationregistry-01.svg +++ b/1-js/99-js-misc/07-weakref-finalizationregistry/weakref-finalizationregistry-01.svg @@ -1,32 +1,183 @@ - - - - + + + + + - - - user - - name: "John" - Object - - <global> - - - - - + + + uživatel + + jméno: "Jan" + Object + + <globální> + + + + + - - - - + + + + - - - + + + - admin + správce - \ No newline at end of file + diff --git a/1-js/99-js-misc/07-weakref-finalizationregistry/weakref-finalizationregistry-02.svg b/1-js/99-js-misc/07-weakref-finalizationregistry/weakref-finalizationregistry-02.svg index 6cc199a12..2f45630b1 100644 --- a/1-js/99-js-misc/07-weakref-finalizationregistry/weakref-finalizationregistry-02.svg +++ b/1-js/99-js-misc/07-weakref-finalizationregistry/weakref-finalizationregistry-02.svg @@ -1,33 +1,166 @@ - - - - + + + + + - - - - - <global> - - - name: "John" - Object + + + + + <globální> + + + jméno: "Jan" + Object - - - - + + + + - - - - + + + + - admin + správce - - + + - - \ No newline at end of file + diff --git a/1-js/99-js-misc/07-weakref-finalizationregistry/weakref-finalizationregistry-03.svg b/1-js/99-js-misc/07-weakref-finalizationregistry/weakref-finalizationregistry-03.svg index 949a14f9f..1ee543089 100644 --- a/1-js/99-js-misc/07-weakref-finalizationregistry/weakref-finalizationregistry-03.svg +++ b/1-js/99-js-misc/07-weakref-finalizationregistry/weakref-finalizationregistry-03.svg @@ -1,75 +1,405 @@ - - - - + + + + + - - - - - - - - - - key - value - image-01.jpg - image-02.jpg - image-03.jpg - - - - - - + + + + + + + + + + klíč + hodnota + image-01.jpg + image-02.jpg + image-03.jpg + + + + + + - - - - + + + + - WeakRef object - - - + objekt WeakRef + + + - - - - - - - - - - - WeakRef object - - + + + + + + + + + + + objekt WeakRef + + - - - - + + + + - - - - - - - - WeakRef object - - - - - - - \ No newline at end of file + + + + + + + + objekt WeakRef + + + + + + + diff --git a/1-js/99-js-misc/07-weakref-finalizationregistry/weakref-finalizationregistry-04.svg b/1-js/99-js-misc/07-weakref-finalizationregistry/weakref-finalizationregistry-04.svg index 1177d6580..1104bd759 100644 --- a/1-js/99-js-misc/07-weakref-finalizationregistry/weakref-finalizationregistry-04.svg +++ b/1-js/99-js-misc/07-weakref-finalizationregistry/weakref-finalizationregistry-04.svg @@ -1,77 +1,434 @@ - - - - + + + + + - - name: "John" - Object - - admin - - - - - - - - - key - value - image-01.jpg - image-02.jpg - image-03.jpg - - - - - - + + jméno: "Jan" + Object + + admin + + + + + + + + + klíč + hodnota + image-01.jpg + image-02.jpg + image-03.jpg + + + + + + - - - - + + + + - WeakRef object - - - + objekt WeakRef + + + - - - - - - - - - - - WeakRef object - - + + + + + + + + + + + objekt WeakRef + + - undefined - undefined + undefined + undefined - - - - + + + + - - - - - - - - WeakRef object - - - \ No newline at end of file + + + + + + + + objekt WeakRef + + + diff --git a/1-js/99-js-misc/07-weakref-finalizationregistry/weakref-finalizationregistry-05.svg b/1-js/99-js-misc/07-weakref-finalizationregistry/weakref-finalizationregistry-05.svg index e738f8e7e..93119f5da 100644 --- a/1-js/99-js-misc/07-weakref-finalizationregistry/weakref-finalizationregistry-05.svg +++ b/1-js/99-js-misc/07-weakref-finalizationregistry/weakref-finalizationregistry-05.svg @@ -1,103 +1,550 @@ - - - - + + + + + - - - - - - - - - - - image-02.jpg - image-03.jpg + + + + + + + + + + + image-02.jpg + image-03.jpg - key - value - image-01.jpg - - - - - - - - - - - - - - - - + klíč + hodnota + image-01.jpg + + + + + + + + + + + + + + + + - - - - - - + + + + + + - - - - - - - + + + + + + + - - - - + + + + - WeakRef object - - - + objekt WeakRef + + + - - - - - - - - - - - WeakRef object - - + + + + + + + + + + + objekt WeakRef + + - undefined - undefined - Deleted by FinalizationRegistry cleanup callback + undefined + undefined + Smazáno úklidovým callbackem FinalizationRegistry - - - - + + + + - - - - - - - - WeakRef object - - - - \ No newline at end of file + + + + + + + + objekt WeakRef + + + + diff --git a/1-js/99-js-misc/07-weakref-finalizationregistry/weakref-finalizationregistry.view/index.html b/1-js/99-js-misc/07-weakref-finalizationregistry/weakref-finalizationregistry.view/index.html index 7ce52f927..92bbdf849 100644 --- a/1-js/99-js-misc/07-weakref-finalizationregistry/weakref-finalizationregistry.view/index.html +++ b/1-js/99-js-misc/07-weakref-finalizationregistry/weakref-finalizationregistry.view/index.html @@ -4,7 +4,7 @@ - Photo Library Collage + Koláž fotoknihovny @@ -12,7 +12,7 @@

- Photo Library Collage + Koláž fotoknihovny

@@ -24,9 +24,9 @@

- - - + + +
diff --git a/2-ui/1-document/01-browser-environment/article.md b/2-ui/1-document/01-browser-environment/article.md index eedc28fb3..d157990ae 100644 --- a/2-ui/1-document/01-browser-environment/article.md +++ b/2-ui/1-document/01-browser-environment/article.md @@ -1,113 +1,113 @@ -# Browser environment, specs +# Prostředí prohlížeče a jeho specifikace -The JavaScript language was initially created for web browsers. Since then, it has evolved into a language with many uses and platforms. +Jazyk JavaScript byl původně vytvořen pro webové prohlížeče. Od té doby se vyvinul v jazyk se širokým využitím na mnoha platformách. -A platform may be a browser, or a web-server or another *host*, or even a "smart" coffee machine if it can run JavaScript. Each of these provides platform-specific functionality. The JavaScript specification calls that a *host environment*. +Platformou může být prohlížeč, webový server nebo jiný *hostitel*, třeba i „chytrý“ automat na kávu, pokud dokáže spouštět JavaScriptové skripty. Každý z nich poskytuje vlastní specifickou funkcionalitu. Specifikace JavaScriptu ji nazývá *hostitelské prostředí*. -A host environment provides its own objects and functions in addition to the language core. Web browsers give a means to control web pages. Node.js provides server-side features, and so on. +Hostitelské prostředí poskytuje k jádru jazyka navíc své vlastní objekty a funkce. Webové prohlížeče poskytují způsoby, jak ovládat webové stránky, Node.js poskytuje prvky pro serverovou stranu a tak dále. -Here's a bird's-eye view of what we have when JavaScript runs in a web browser: +Pohled z ptačí perspektivy nám ukazuje, co máme, když spouštíme JavaScript ve webovém prohlížeči: ![](windowObjects.svg) -There's a "root" object called `window`. It has two roles: +Je zde „kořenový“ objekt nazvaný `window`, který má dvě role: -1. First, it is a global object for JavaScript code, as described in the chapter . -2. Second, it represents the "browser window" and provides methods to control it. +1. Za prvé, je to globální objekt pro JavaScriptový kód, jak je popsáno v kapitole . +2. Za druhé, představuje „okno prohlížeče“ a poskytuje metody, jak je ovládat. -For instance, we can use it as a global object: +Můžeme jej například použít jako globální objekt: ```js run global -function sayHi() { - alert("Hello"); +function řekniAhoj() { + alert("Ahoj"); } -// global functions are methods of the global object: -window.sayHi(); +// globální funkce jsou metody globálního objektu: +window.řekniAhoj(); ``` -And we can use it as a browser window, to show the window height: +A můžeme jej použít jako okno prohlížeče, abychom si zobrazili výšku okna: ```js run -alert(window.innerHeight); // inner window height +alert(window.innerHeight); // výška vnitřního okna ``` -There are more window-specific methods and properties, which we'll cover later. +Existují i další metody a vlastnosti specifické pro okna, které probereme později. ## DOM (Document Object Model) -The Document Object Model, or DOM for short, represents all page content as objects that can be modified. +Document Object Model, zkráceně DOM, představuje veškerý obsah stránky jako objekty, které mohou být modifikovány. -The `document` object is the main "entry point" to the page. We can change or create anything on the page using it. +Hlavním „vstupním bodem“ stránky je objekt `document`. S jeho pomocí můžeme na stránce cokoli změnit nebo vytvořit. -For instance: +Například: ```js run -// change the background color to red +// změníme barvu pozadí na červenou document.body.style.background = "red"; -// change it back after 1 second +// po 1 sekundě ji změníme zpět setTimeout(() => document.body.style.background = "", 1000); ``` -Here, we used `document.body.style`, but there's much, much more. Properties and methods are described in the specification: [DOM Living Standard](https://dom.spec.whatwg.org). +Tady jsme použili `document.body.style`, ale je toho mnohem, mnohem více. Vlastnosti a metody jsou popsány ve specifikaci: [DOM Living Standard](https://dom.spec.whatwg.org). -```smart header="DOM is not only for browsers" -The DOM specification explains the structure of a document and provides objects to manipulate it. There are non-browser instruments that use DOM too. +```smart header="DOM není jen pro prohlížeče" +Specifikace DOMu vysvětluje strukturu dokumentu a poskytuje objekty, pomocí nichž s ní lze manipulovat. Kromě prohlížečů existují i jiné nástroje, které používají DOM. -For instance, server-side scripts that download HTML pages and process them can also use the DOM. They may support only a part of the specification though. +Například DOM mohou používat i skripty na straně serveru, které stahují a zpracovávají HTML stránky. Ty však mohou podporovat jen část specifikace. ``` -```smart header="CSSOM for styling" -There's also a separate specification, [CSS Object Model (CSSOM)](https://www.w3.org/TR/cssom-1/) for CSS rules and stylesheets, that explains how they are represented as objects, and how to read and write them. +```smart header="CSSOM pro nastavování stylů" +Existuje také samostatná specifikace [CSS Object Model (CSSOM)](https://www.w3.org/TR/cssom-1/) pro CSS pravidla a styly, která vysvětluje, jakým způsobem jsou reprezentovány v podobě objektů a jak je lze načítat a ukládat. -The CSSOM is used together with the DOM when we modify style rules for the document. In practice though, the CSSOM is rarely required, because we rarely need to modify CSS rules from JavaScript (usually we just add/remove CSS classes, not modify their CSS rules), but that's also possible. +Když měníme pravidla stylů v dokumentu, CSSOM se používá společně s DOMem. V praxi je však CSSOM zapotřebí jen zřídka, jelikož málokdy potřebujeme měnit CSS pravidla v JavaScriptu (obvykle jen přidáváme a odebíráme CSS třídy, neměníme jejich CSS pravidla), ale i to je možné provést. ``` ## BOM (Browser Object Model) -The Browser Object Model (BOM) represents additional objects provided by the browser (host environment) for working with everything except the document. +Browser Object Model (BOM) představuje další objekty, které poskytuje prohlížeč (hostitelské prostředí) pro práci se vším ostatním kromě dokumentu. -For instance: +Například: -- The [navigator](mdn:api/Window/navigator) object provides background information about the browser and the operating system. There are many properties, but the two most widely known are: `navigator.userAgent` -- about the current browser, and `navigator.platform` -- about the platform (can help to differentiate between Windows/Linux/Mac etc). -- The [location](mdn:api/Window/location) object allows us to read the current URL and can redirect the browser to a new one. +- Objekt [navigator](mdn:api/Window/navigator) poskytuje informace o prohlížeči a operačním systému. Obsahuje mnoho vlastností, ale dvě nejznámější jsou: `navigator.userAgent` -- o aktuálním prohlížeči, a `navigator.platform` -- o platformě (může pomoci rozlišit Windows/Linux/Mac atd.). +- Objekt [location](mdn:api/Window/location) nám umožňuje načíst aktuální URL a může přesměrovat prohlížeč na jiné. -Here's how we can use the `location` object: +Takto můžeme objekt `location` použít: ```js run -alert(location.href); // shows current URL -if (confirm("Go to Wikipedia?")) { - location.href = "https://wikipedia.org"; // redirect the browser to another URL +alert(location.href); // zobrazí aktuální URL +if (confirm("Přejít na Wikipedii?")) { + location.href = "https://cs.wikipedia.org"; // přesměruje prohlížeč na jiné URL } ``` -The functions `alert/confirm/prompt` are also a part of the BOM: they are not directly related to the document, but represent pure browser methods for communicating with the user. +Součástí BOMu jsou i funkce `alert/confirm/prompt`: ty se nevztahují přímo k dokumentu, ale představují čistě prohlížečové metody pro komunikaci s uživatelem. -```smart header="Specifications" -The BOM is a part of the general [HTML specification](https://html.spec.whatwg.org). +```smart header="Specifikace" +BOM je součástí všeobecné [specifikace HTML](https://html.spec.whatwg.org). -Yes, you heard that right. The HTML spec at is not only about the "HTML language" (tags, attributes), but also covers a bunch of objects, methods, and browser-specific DOM extensions. That's "HTML in broad terms". Also, some parts have additional specs listed at . +Ano, čtete správně. Specifikace HTML na není jen o „jazyce HTML“ (značky, atributy), ale pokrývá i hromadu objektů, metod a rozšíření DOMu specifických pro prohlížeče. Je to „HTML v širším slova smyslu“. Navíc některé části mají další specifikace, které jsou uvedeny na . ``` -## Summary +## Shrnutí -Talking about standards, we have: +Hovoříme-li o standardech, pak máme: -DOM specification -: Describes the document structure, manipulations, and events, see . +Specifikaci DOM +: Popisuje strukturu dokumentu, manipulaci s ní a události dokumentu, viz . -CSSOM specification -: Describes stylesheets and style rules, manipulations with them, and their binding to documents, see . +Specifikaci CSSOM +: Popisuje styly a jejich pravidla, manipulaci s nimi a jejich vazbu na dokument, viz . -HTML specification -: Describes the HTML language (e.g. tags) and also the BOM (browser object model) -- various browser functions: `setTimeout`, `alert`, `location` and so on, see . It takes the DOM specification and extends it with many additional properties and methods. +Specifikaci HTML +: Popisuje jazyk HTML (např. jeho značky) a také BOM (browser object model -- objektový model prohlížeče) -- různé funkce prohlížeče: `setTimeout`, `alert`, `location` a podobně, viz . Přebírá specifikaci DOMu a rozšiřuje ji o mnoho dalších vlastností a metod. -Additionally, some classes are described separately at . +Některé třídy jsou navíc popsány odděleně na . -Please note these links, as there's so much to learn that it's impossible to cover everything and remember it all. +Tyto odkazy si prosím zapamatujte, neboť tady je toho k naučení tolik, že je nemožné to všechno obsáhnout a pamatovat si. -When you'd like to read about a property or a method, the Mozilla manual at is also a nice resource, but the corresponding spec may be better: it's more complex and longer to read, but will make your fundamental knowledge sound and complete. +Kdybyste si chtěli přečíst o nějaké vlastnosti nebo metodě, pěkným zdrojem je i manuál Mozilly na , ale příslušná specifikace může být lepší: je sice složitější a delší na přečtení, ale poskytne vám solidní a úplné základní znalosti. -To find something, it's often convenient to use an internet search "WHATWG [term]" or "MDN [term]", e.g , . +Když chcete něco najít, často se vyplatí použít internetové hledání „WHATWG [pojem]“ nebo „MDN [pojem]“, např. , . -Now, we'll get down to learning the DOM, because the document plays the central role in the UI. +Nyní přejdeme k učení DOMu, jelikož hlavní roli v uživatelském rozhraní hraje dokument. diff --git a/2-ui/1-document/02-dom-nodes/article.md b/2-ui/1-document/02-dom-nodes/article.md index f7f2be91d..6d8d7d2dd 100644 --- a/2-ui/1-document/02-dom-nodes/article.md +++ b/2-ui/1-document/02-dom-nodes/article.md @@ -4,49 +4,49 @@ libs: --- -# DOM tree +# DOM strom -The backbone of an HTML document is tags. +Páteří každého HTML dokumentu jsou značky neboli tagy. -According to the Document Object Model (DOM), every HTML tag is an object. Nested tags are "children" of the enclosing one. The text inside a tag is an object as well. +Podle DOMu (Document Object Model) je každá HTML značka objekt. Vnořené značky jsou „dětmi“ vnějších. Text uvnitř značky je také objekt. -All these objects are accessible using JavaScript, and we can use them to modify the page. +Všechny tyto objekty jsou v JavaScriptu dostupné a my můžeme s jejich pomocí měnit stránku. -For example, `document.body` is the object representing the `` tag. +Například `document.body` je objekt, který představuje značku ``. -Running this code will make the `` red for 3 seconds: +Po spuštění tohoto kódu `` na 3 sekundy změní barvu na červenou: ```js run -document.body.style.background = 'red'; // make the background red +document.body.style.background = 'red'; // změní barvu pozadí na červenou -setTimeout(() => document.body.style.background = '', 3000); // return back +setTimeout(() => document.body.style.background = '', 3000); // vrátí ji zpět ``` -Here we used `style.background` to change the background color of `document.body`, but there are many other properties, such as: +Zde jsme použili `style.background`, abychom změnili barvu pozadí `document.body`, ale existuje mnoho dalších vlastností, například: -- `innerHTML` -- HTML contents of the node. -- `offsetWidth` -- the node width (in pixels) -- ...and so on. +- `innerHTML` -- HTML obsah uzlu, +- `offsetWidth` -- šířka uzlu (v pixelech), +- ...a tak dále. -Soon we'll learn more ways to manipulate the DOM, but first we need to know about its structure. +Brzy se naučíme další způsoby, jak manipulovat s DOMem, ale nejprve musíme poznat jeho strukturu. -## An example of the DOM +## Příklad DOMu -Let's start with the following simple document: +Začněme s následujícím jednoduchým dokumentem: ```html run no-beautify - About elk + O losovi - The truth about elk. + Pravda o losovi. ``` -The DOM represents HTML as a tree structure of tags. Here's how it looks: +DOM reprezentuje HTML v podobě stromové struktury značek. Vypadá následovně:
@@ -57,35 +57,35 @@ drawHtmlTree(node1, 'div.domtree', 690, 320); ```online -On the picture above, you can click on element nodes and their children will open/collapse. +Na uvedeném obrázku můžete klikat na elementové uzly a jejich děti se budou rozbalovat a schovávat. ``` -Every tree node is an object. +Každý uzel stromu je objektem. -Tags are *element nodes* (or just elements) and form the tree structure: `` is at the root, then `` and `` are its children, etc. +Značky jsou *elementové uzly* (nebo jen elementy) a tvoří strukturu stromu: jeho kořenem je ``, jeho dětmi jsou `` a ``, a tak dále. -The text inside elements forms *text nodes*, labelled as `#text`. A text node contains only a string. It may not have children and is always a leaf of the tree. +Text uvnitř elementů tvoří *textové uzly*, označené jako `#text`. Textový uzel obsahuje pouze řetězec. Nesmí mít děti a je vždy listem stromu. -For instance, the `` tag has the text `"About elk"`. +Například značka `<title>` obsahuje text `"O losovi"`. -Please note the special characters in text nodes: +Prosíme, všimněte si těchto zvláštních znaků v textových uzlech: -- a newline: `↵` (in JavaScript known as `\n`) -- a space: `␣` +- konec řádku: `↵` (v JavaScriptu znám jako `\n`) +- mezera: `␣` -Spaces and newlines are totally valid characters, like letters and digits. They form text nodes and become a part of the DOM. So, for instance, in the example above the `<head>` tag contains some spaces before `<title>`, and that text becomes a `#text` node (it contains a newline and some spaces only). +Mezery a konce řádků jsou zcela platnými znaky, tak jako písmena a číslice. Tvoří textové uzly a stávají se součástí DOMu. Například v uvedeném příkladu značka `<head>` obsahuje před `<title>` několik mezer, které se staly uzlem `#text` (který obsahuje pouze znak konce řádku a několik mezer). -There are only two top-level exclusions: -1. Spaces and newlines before `<head>` are ignored for historical reasons. -2. If we put something after `</body>`, then that is automatically moved inside the `body`, at the end, as the HTML spec requires that all content must be inside `<body>`. So there can't be any spaces after `</body>`. +Existují jen dvě výjimky na nejvyšší úrovni: +1. Mezery a konce řádků před `<head>` se z historických důvodů ignorují. +2. Jestliže vložíme něco za `</body>`, bude to automaticky přemístěno dovnitř `body` na konec, jelikož specifikace HTML vyžaduje, aby všechen obsah byl uvnitř `<body>`. Za `</body>` tedy nemohou být žádné mezery. -In other cases everything's straightforward -- if there are spaces (just like any character) in the document, then they become text nodes in the DOM, and if we remove them, then there won't be any. +V ostatních případech je všechno jasné -- jestliže jsou v dokumentu mezery (stejně jako kterýkoli jiný znak), stanou se v DOMu textovými uzly, a pokud je odstraníme, nebudou tam. -Here are no space-only text nodes: +Zde nejsou žádné textové uzly, které by obsahovaly jen mezery: ```html no-beautify <!DOCTYPE HTML> -<html><head><title>About elkThe truth about elk. +O losoviPravda o losovi. ```
@@ -96,21 +96,21 @@ let node2 = {"name":"HTML","nodeType":1,"children":[{"name":"HEAD","nodeType":1, drawHtmlTree(node2, 'div.domtree', 690, 210); -```smart header="Spaces at string start/end and space-only text nodes are usually hidden in tools" -Browser tools (to be covered soon) that work with DOM usually do not show spaces at the start/end of the text and empty text nodes (line-breaks) between tags. +```smart header="Mezery na začátku a konci řetězce a textové uzly obsahující pouze mezery jsou v nástrojích obvykle skryty" +Prohlížečové nástroje (brzy se o nich dozvíme), které pracují s DOMem, obvykle nezobrazují mezery na začátku a konci textu a prázdné textové uzly (konce řádků) mezi značkami. -Developer tools save screen space this way. +Vývojářské nástroje tímto způsobem šetří místo na obrazovce. -On further DOM pictures we'll sometimes omit them when they are irrelevant. Such spaces usually do not affect how the document is displayed. +Na dalších obrázcích DOMu je také někdy budeme vypouštět, když nebudou mít význam. Tyto mezery zpravidla nemají vliv na to, jak je dokument zobrazen. ``` -## Autocorrection +## Automatické opravy -If the browser encounters malformed HTML, it automatically corrects it when making the DOM. +Jestliže prohlížeč narazí na poškozený HTML kód, při vytváření DOMu jej automaticky opraví. -For instance, the top tag is always ``. Even if it doesn't exist in the document, it will exist in the DOM, because the browser will create it. The same goes for ``. +Například nejvyšší značka bude vždy ``. I kdyby v dokumentu nebyla, bude v DOMu vždy existovat, protože prohlížeč ji vytvoří. Totéž platí pro ``. -As an example, if the HTML file is the single word `"Hello"`, the browser will wrap it into `` and ``, and add the required ``, and the DOM will be: +Například jestliže je HTML soubor tvořen jediným slovem `"Ahoj"`, pak jej prohlížeč zabalí do `` a ``, přidá požadovanou značku `` a DOM bude vypadat následovně:
@@ -121,65 +121,65 @@ let node3 = {"name":"HTML","nodeType":1,"children":[{"name":"HEAD","nodeType":1, drawHtmlTree(node3, 'div.domtree', 690, 150); -While generating the DOM, browsers automatically process errors in the document, close tags and so on. +Prohlížeče při generování DOMu automaticky zpracují chyby v dokumentu, uzavřou značky a podobně. -A document with unclosed tags: +Dokument s neuzavřenými značkami: ```html no-beautify -

Hello -

  • Mom -
  • and -
  • Dad +

    Ahoj +

  • mami +
  • a +
  • tati ``` -...will become a normal DOM as the browser reads tags and restores the missing parts: +...se stane normálním DOMem, jelikož prohlížeč načte značky a obnoví chybějící části:
    -````warn header="Tables always have ``" -An interesting "special case" is tables. By DOM specification they must have `` tag, but HTML text may omit it. Then the browser creates `` in the DOM automatically. +````warn header="Tabulky mají vždy ``" +Zajímavým „zvláštním případem“ jsou tabulky. Podle specifikace DOMu musejí mít značku ``, ale HTML kód ji může vynechat. Pak prohlížeč vytvoří `` v DOMu automaticky. -For the HTML: +Pro HTML: ```html no-beautify -
    1
    +
    1
    ``` -DOM-structure will be: +Struktura DOMu bude následující:
    -You see? The `` appeared out of nowhere. We should keep this in mind while working with tables to avoid surprises. +Vidíte? Značka `` se zjevila odnikud. Při práci s tabulkami bychom to měli mít na paměti, abychom se vyhnuli překvapením. ```` -## Other node types +## Ostatní typy uzlů -There are some other node types besides elements and text nodes. +Existují i jiné typy uzlů, než elementové a textové. -For example, comments: +Například komentáře: ```html - The truth about elk. + Pravda o losovi.
      -
    1. An elk is a smart
    2. +
    3. Los je elegantní
    4. *!* - + */!* -
    5. ...and cunning animal!
    6. +
    7. ...a mazané zvíře!
    @@ -188,95 +188,96 @@ For example, comments:
    -We can see here a new tree node type -- *comment node*, labeled as `#comment`, between two text nodes. +Tady vidíme mezi dvěma textovými uzly nový typ stromového uzlu -- *komentářový uzel*, označený jako `#comment`. -We may think -- why is a comment added to the DOM? It doesn't affect the visual representation in any way. But there's a rule -- if something's in HTML, then it also must be in the DOM tree. +Může nás napadnout -- proč se vlastně do DOMu přidává komentář? Ten přece nemá na vzhled stránky žádný vliv. Existuje však pravidlo -- jestliže je něco v HTML, musí to být i v DOM stromu. -**Everything in HTML, even comments, becomes a part of the DOM.** +**Vše v HTML, včetně komentářů, se stává součástí DOMu.** -Even the `` directive at the very beginning of HTML is also a DOM node. It's in the DOM tree right before ``. Few people know about that. We are not going to touch that node, we even don't draw it on diagrams, but it's there. +Dokonce i direktiva `` na samém začátku HTML je DOM uzlem. V DOM stromu se nachází těsně před ``. O tom ví jen málokdo. Nebudeme na tento uzel sahat, nebudeme jej ani kreslit v diagramech, ale je tam. -The `document` object that represents the whole document is, formally, a DOM node as well. +Objekt `document`, který představuje celý dokument, je formálně také DOM uzlem. -There are [12 node types](https://dom.spec.whatwg.org/#node). In practice we usually work with 4 of them: +Celkem existuje [12 typů uzlů](https://dom.spec.whatwg.org/#node). V praxi obvykle pracujeme se čtyřmi z nich: -1. `document` -- the "entry point" into DOM. -2. element nodes -- HTML-tags, the tree building blocks. -3. text nodes -- contain text. -4. comments -- sometimes we can put information there, it won't be shown, but JS can read it from the DOM. +1. `document` -- „vstupní bod“ DOMu. +2. elementové uzly -- HTML značky, stavební kameny stromu. +3. textové uzly -- obsahují text. +4. komentáře -- někdy do nich můžeme vkládat informace, které se nezobrazí, ale JS je může z DOMu načíst. -## See it for yourself +## Podívejte se sami -To see the DOM structure in real-time, try [Live DOM Viewer](https://software.hixie.ch/utilities/js/live-dom-viewer/). Just type in the document, and it will show up as a DOM at an instant. +Chcete-li vidět strukturu DOMu v reálném čase, zkuste [Live DOM Viewer](https://software.hixie.ch/utilities/js/live-dom-viewer/). Stačí psát do dokumentu a ten se za okamžik zobrazí jako DOM. -Another way to explore the DOM is to use the browser developer tools. Actually, that's what we use when developing. +Dalším způsobem, jak prozkoumávat DOM, je používat prohlížečové vývojářské nástroje. Právě ty používáme při programování. -To do so, open the web page [elk.html](elk.html), turn on the browser developer tools and switch to the Elements tab. +Abyste tak učinili, otevřete si webovou stránku [elk.html](elk.html), zapněte si prohlížečové vývojářské nástroje a přepněte se na záložku Elements (Prvky). -It should look like this: +Měla by vypadat přibližně takto: ![](elk.svg) -You can see the DOM, click on elements, see their details and so on. -Please note that the DOM structure in developer tools is simplified. Text nodes are shown just as text. And there are no "blank" (space only) text nodes at all. That's fine, because most of the time we are interested in element nodes. +Vidíte DOM, klikáte na elementy, vidíte jejich detaily a podobně. -Clicking the button in the left-upper corner allows us to choose a node from the webpage using a mouse (or other pointer devices) and "inspect" it (scroll to it in the Elements tab). This works great when we have a huge HTML page (and corresponding huge DOM) and would like to see the place of a particular element in it. +Prosíme všimněte si, že struktura DOMu ve vývojářských nástrojích je zjednodušená. Textové uzly jsou zobrazeny pouze jako text. A „prázdné“ textové uzly (obsahující jen mezery) nejsou zobrazeny vůbec. To je dobře, neboť ve většině případů nás zajímají pouze elementové uzly. -Another way to do it would be just right-clicking on a webpage and selecting "Inspect" in the context menu. +Po kliknutí na tlačítko v levém horním rohu si můžeme zvolit uzel z webové stránky myší (nebo jiným ukazovacím zařízením) a „prozkoumat“ jej (záložka Elements se na něj posune). To funguje skvěle, když máme obrovskou HTML stránku (a odpovídající obrovský DOM) a chceme se podívat na umístění určitého jejího elementu. + +Další způsob, jak to udělat, je kliknout pravým tlačítkem na webovou stránku a v kontextovém menu zvolit „Prozkoumat“ („Inspect“). ![](inspect.svg) -At the right part of the tools there are the following subtabs: -- **Styles** -- we can see CSS applied to the current element rule by rule, including built-in rules (gray). Almost everything can be edited in-place, including the dimensions/margins/paddings of the box below. -- **Computed** -- to see CSS applied to the element by property: for each property we can see a rule that gives it (including CSS inheritance and such). -- **Event Listeners** -- to see event listeners attached to DOM elements (we'll cover them in the next part of the tutorial). -- ...and so on. +V pravé části nástrojů se nacházejí následující podzáložky: +- **Styles (Styly)** -- můžeme vidět CSS aplikované na aktuální element, jedno pravidlo po druhém, včetně vestavěných pravidel (šedě zobrazených). Téměř všechno můžeme na místě editovat, včetně rozměrů a vnějších i vnitřních okrajů boxu. +- **Computed (Vypočteno)** -- vidíme CSS aplikované na element podle vlastností: pro každou vlastnost vidíme pravidlo, které ji definuje (včetně CSS dědičnosti a podobně). +- **Event Listeners (Posluchače událostí)** -- vidíme posluchače událostí připojené k DOM elementům (probereme je v příští části tutoriálu). +- ...a tak dále. -The best way to study them is to click around. Most values are editable in-place. +Nejlepší způsob, jak je prostudovat, je klikat kolem dokola. Většinu hodnot lze na místě editovat. -## Interaction with console +## Interakce s konzolí -As we work the DOM, we also may want to apply JavaScript to it. Like: get a node and run some code to modify it, to see the result. Here are few tips to travel between the Elements tab and the console. +Při práci s DOMem na něj můžeme také chtít aplikovat JavaScript. Například můžeme chtít načíst uzel a spustit nějaký kód, který ho modifikuje, abychom viděli výsledek. Poskytneme několik rad, jak cestovat mezi záložkou Elements a konzolí. -For the start: +Pro začátek: -1. Select the first `
  • ` in the Elements tab. -2. Press `key:Esc` -- it will open console right below the Elements tab. +1. Na záložce Elements zvolte první značku `
  • `. +2. Stiskněte `key:Esc` -- přímo pod záložkou Elements se otevře konzole. -Now the last selected element is available as `$0`, the previously selected is `$1` etc. +Nyní je poslední zvolený element k dispozici jako `$0`, předposlední zvolený jako `$1`, a tak dále. -We can run commands on them. For instance, `$0.style.background = 'red'` makes the selected list item red, like this: +Můžeme na nich spouštět příkazy. Například `$0.style.background = 'red'` obarví zvolený prvek seznamu červeně, takto: ![](domconsole0.svg) -That's how to get a node from Elements in Console. +Tímto způsobem tedy získáme uzel ze záložky Elements v konzoli. -There's also a road back. If there's a variable referencing a DOM node, then we can use the command `inspect(node)` in Console to see it in the Elements pane. +Existuje i opačná cesta. Jestliže se nějaká proměnná odkazuje na DOM uzel, můžeme v konzoli použít příkaz `inspect(uzel)`, abychom jej viděli v záložce Elements. -Or we can just output the DOM node in the console and explore "in-place", like `document.body` below: +Nebo si prostě můžeme vypsat DOM uzel v konzoli a prozkoumat jej „na místě“, například `document.body` následovně: ![](domconsole1.svg) -That's for debugging purposes of course. From the next chapter on we'll access and modify DOM using JavaScript. +To samozřejmě slouží pro účely ladění. Od následující kapitoly budeme k DOMu přistupovat a modifikovat jej pomocí JavaScriptu. -The browser developer tools are a great help in development: we can explore the DOM, try things and see what goes wrong. +Prohlížečové vývojářské nástroje představují při vývoji značnou pomoc: můžeme prozkoumávat DOM, zkoušet různé věci a vidíme, co se pokazilo. -## Summary +## Shrnutí -An HTML/XML document is represented inside the browser as the DOM tree. +HTML/XML dokument je v prohlížeči reprezentován DOM stromem. -- Tags become element nodes and form the structure. -- Text becomes text nodes. -- ...etc, everything in HTML has its place in DOM, even comments. +- Značky se stávají elementovými uzly a tvoří jeho strukturu. +- Text se stává textovými uzly. +- ...atd., vše, co je v HTML, včetně komentářů, má v DOMu své místo. -We can use developer tools to inspect DOM and modify it manually. +Pomocí vývojářských nástrojů můžeme DOM prozkoumávat a ručně jej měnit. -Here we covered the basics, the most used and important actions to start with. There's an extensive documentation about Chrome Developer Tools at . The best way to learn the tools is to click here and there, read menus: most options are obvious. Later, when you know them in general, read the docs and pick up the rest. +V této kapitole jsme uvedli základy, nejpoužívanější a nejdůležitější akce, s kterými začneme. Rozsáhlá dokumentace vývojářských nástrojů Chrome (Chrome Developer Tools) se nachází na . Nejlepší způsob, jak se naučit nástroje používat, je klikat sem a tam a číst menu: většina možností je zřejmá. Až je budete později obecně znát, přečtěte si dokumentaci a naučte se zbytek. -DOM nodes have properties and methods that allow us to travel between them, modify them, move around the page, and more. We'll get down to them in the next chapters. +DOM uzly obsahují vlastnosti a metody, které nám umožňují mezi nimi cestovat, měnit je, přesunovat je na stránce a podobně. Dostaneme se k nim v dalších kapitolách. diff --git a/2-ui/1-document/02-dom-nodes/elk.html b/2-ui/1-document/02-dom-nodes/elk.html index dc5d65f54..49b30586f 100644 --- a/2-ui/1-document/02-dom-nodes/elk.html +++ b/2-ui/1-document/02-dom-nodes/elk.html @@ -1,11 +1,11 @@ - The truth about elk. + Pravda o losovi.
      -
    1. An elk is a smart
    2. +
    3. Los je elegantní
    4. -
    5. ...and cunning animal!
    6. +
    7. ...a mazané zvíře!
    diff --git a/2-ui/1-document/03-dom-navigation/1-dom-children/solution.md b/2-ui/1-document/03-dom-navigation/1-dom-children/solution.md index decfa62c7..7c36aaacf 100644 --- a/2-ui/1-document/03-dom-navigation/1-dom-children/solution.md +++ b/2-ui/1-document/03-dom-navigation/1-dom-children/solution.md @@ -1,27 +1,27 @@ -There are many ways, for instance: +Způsobů je mnoho, například: -The `
    ` DOM node: +DOM uzel `
    `: ```js document.body.firstElementChild -// or +// nebo document.body.children[0] -// or (the first node is space, so we take 2nd) +// nebo (první uzel je mezerový, takže vezmeme až druhý) document.body.childNodes[1] ``` -The `