Moduly v JavaScripte
Časť 1: Module Pattern
Milan Herda, 10/2016, úpravy 08/2022
Úloha
Úloha
Vytvorte v JS objekt, ktorý bude mať privátnu premennú name, ku ktorej sa bude dať pristúpiť iba pomocou getter a setter metód
// váš kód
const person = /* váš kód */;
person.setName('fero');
console.log(
person.getName()
);
Scope premenných
Scope je rozsah platnosti, tj. kde všade je možné k existujúcej premennej pristúpiť.
Je určený miestom a spôsobom deklarovania premennej.
Scope premenných
Scope je rozsah platnosti, tj. kde všade je možné k existujúcej premennej pristúpiť.
Je určený miestom a spôsobom deklarovania premennej.
Scope premenných
Scope je rozsah platnosti, tj. kde všade je možné k existujúcej premennej pristúpiť.
Je určený miestom a spôsobom deklarovania premennej.
Aký je scope v prípade, že tento kód je v top-level skripte?
a = 1;
var b = 2;
function foo () {
c = 3;
var d = 4;
for (i = 5; i < 10; i++) {
e = 6;
var f = 7;
}
for (var j = 8; j < 10; j++) {
}
}
Aký je scope v prípade, že tento kód je v top-level skripte?
a = 1; // globálna
var b = 2;
function foo () {
c = 3;
var d = 4;
for (i = 5; i < 10; i++) {
e = 6;
var f = 7;
}
for (var j = 8; j < 10; j++) {
}
}
Aký je scope v prípade, že tento kód je v top-level skripte?
a = 1; // globálna
var b = 2; // globálna
function foo () {
c = 3;
var d = 4;
for (i = 5; i < 10; i++) {
e = 6;
var f = 7;
}
for (var j = 8; j < 10; j++) {
}
}
Aký je scope v prípade, že tento kód je v top-level skripte?
a = 1; // globálna
var b = 2; // globálna
function foo () {
c = 3; // globálna
var d = 4;
for (i = 5; i < 10; i++) {
e = 6;
var f = 7;
}
for (var j = 8; j < 10; j++) {
}
}
Aký je scope v prípade, že tento kód je v top-level skripte?
a = 1; // globálna
var b = 2; // globálna
function foo () {
c = 3; // globálna
var d = 4; // lokálna pre foo
for (i = 5; i < 10; i++) {
e = 6;
var f = 7;
}
for (var j = 8; j < 10; j++) {
}
}
Aký je scope v prípade, že tento kód je v top-level skripte?
a = 1; // globálna
var b = 2; // globálna
function foo () {
c = 3; // globálna
var d = 4; // lokálna pre foo
for (i = 5; i < 10; i++) { // globálna
e = 6;
var f = 7;
}
for (var j = 8; j < 10; j++) {
}
}
Aký je scope v prípade, že tento kód je v top-level skripte?
a = 1; // globálna
var b = 2; // globálna
function foo () {
c = 3; // globálna
var d = 4; // lokálna pre foo
for (i = 5; i < 10; i++) { // globálna
e = 6; // globálna
var f = 7;
}
for (var j = 8; j < 10; j++) {
}
}
Aký je scope v prípade, že tento kód je v top-level skripte?
a = 1; // globálna
var b = 2; // globálna
function foo () {
c = 3; // globálna
var d = 4; // lokálna pre foo
for (i = 5; i < 10; i++) { // globálna
e = 6; // globálna
var f = 7; // lokálna pre foo
}
for (var j = 8; j < 10; j++) {
}
}
Aký je scope v prípade, že tento kód je v top-level skripte?
a = 1; // globálna
var b = 2; // globálna
function foo () {
c = 3; // globálna
var d = 4; // lokálna pre foo
for (i = 5; i < 10; i++) { // globálna
e = 6; // globálna
var f = 7; // lokálna pre foo
}
for (var j = 8; j < 10; j++) { // lokálna pre foo
}
}
Ako je to, keď nahradíme var za let?
Ako je to, keď nahradíme var za let?
a = 1;
let b = 2;
function foo () {
c = 3;
let d = 4;
for (i = 5; i < 10; i++) {
e = 6;
let f = 7;
}
for (let j = 8; j < 10; j++) {
}
}
Ako je to, keď nahradíme var za let?
a = 1; // globálna
let b = 2; // globálna
function foo () {
c = 3; // globálna
let d = 4; // lokálna pre foo
for (i = 5; i < 10; i++) { // globálna
e = 6; // globálna
let f = 7; // lokálna pre cyklus
}
for (let j = 8; j < 10; j++) { // lokálna pre cyklus
}
}
A keď použijeme const?
a = 1;
const b = 2;
function foo () {
c = 3;
const d = 4;
for (i = 5; i < 10; i++) {
e = 6;
const f = 7;
}
for (const j = 8; j < 10; j++) {
}
}
A keď použijeme const?
a = 1; // globálna
let b = 2; // globálna
function foo () {
c = 3; // globálna
const d = 4; // lokálna pre foo
for (i = 5; i < 10; i++) { // globálna
e = 6; // globálna
const f = 7; // lokálna pre cyklus
}
for (const j = 8; j < 10; j++) { // TypeError:
// Assignment to constant variable.
}
}
A keď použijeme const?
Spôsoby deklarácie premennej v ES2015
-
var
- bezo zmeny, deklaruje lokálne pre funkciu -
let
- platnosť iba vo svojom bloku -
const
- konštanta(?), platnosť iba vo svojom bloku
Closure
Closure
Closure je "obálka", ktorú vytvára funkcia a ktorá v sebe obsahuje všetky premenné, ku ktorým má funkcia prístup.
*Môže obsahovať premenné deklarované vo funkciách, ktorých beh už dávno skončil
Closure
const a = 1;
function foo () {
const b = 2;
return function () {
const c = 3;
return a + b + c;
}
}
const bar = foo();
bar();
IIFE
IIFE
Immediately Invoked Function Expression
IIFE
(function () {
// kód
})();
K čomu to je?
Nájdite rozdiel
var a = 1;
var b = 2;
var c = a + b;
(function () {
var a = 1;
var b = 2;
var c = a + b;
})();
K čomu to je?
Nájdite rozdiel
var a = 1;
var b = 2;
var c = a + b;
// Premenné sú dostupné
// v globálnom kontexte
(function () {
var a = 1;
var b = 2;
var c = a + b;
})();
// Premenné sú lokálne
// pre anonymnú funkciu
// Nehrozí konflikt
// medzi knižnicami
Module Pattern
Module Pattern
Spôsob, ako pomocou closure vieme vytvárať moduly/objekty s privátnymi premennými/funkciami
Module Pattern
function () {
let name;
return {
setName: function (newName) {
name = newName;
},
getName: function () {
return name;
},
};
}
Revealing Module Pattern
function () {
let name;
const setName = function (newName) {
name = newName;
};
const getName = function () {
return name;
};
// von poskytneme iba metódy, ktoré chceme
return {
setName,
getName,
};
}
Vytvorenie inštancie objektu
const person = (function () {
let name;
const setName = function (newName) {
name = newName;
};
const getName = function () {
return name;
};
// von poskytneme iba metódy, ktoré chceme
return {
setName,
getName,
};
})();
Vytvorenie inštancie objektu cez factory
const personFactory = function () {
let name;
const setName = function (newName) {
name = newName;
};
const getName = function () {
return name;
};
// von poskytneme iba metódy, ktoré chceme
return {
setName,
getName,
};
};
const personA = personFactory();
const personB = personFactory();
Kontrolná otázka
const personFactory = function () {
let name;
const setName = function (newName) {
name = newName;
};
const getName = function () {
return name;
};
// von poskytneme iba metódy, ktoré chceme
return {
setName,
getName,
};
};
const personA = personFactory();
const personB = personFactory();
Ako nastavíme úvodnú hodnotu pri vytvorení inštancie?
Kontrolná otázka
const personFactory = function (initialName) {
let name = initialName;
const setName = function (newName) {
name = newName;
};
const getName = function () {
return name;
};
// von poskytneme iba metódy, ktoré chceme
return {
setName,
getName,
};
};
const personA = personFactory('fero');
const personB = personFactory('jozo');
Pohrajte sa
Úloha
Vytvorte modul reprezentujúci bojovú jednotku v hre s vlastnosťami:
- názov
- rýchlosť
- sila
- zdravie
const unitFactory = function () {
let name;
let speed;
// ...
const setName = function (newName) {
name = newName;
};
const getName = function () {
return name;
};
const setSpeed = function (newSpeed) {
speed = newSpeed;
};
const getSpeed = function () {
return speed;
};
// ...
return {
setName,
getName,
setSpeed,
getSpeed,
//...,
};
};
Úloha
Vytvorte tri inštancie reprezentujúce:
- kopijníka,
- jazdca
- a lukostrelca
const pikeman = unitFactory();
const horseman = unitFactory();
const archer = unitFactory();
pikeman.setName('pikeman');
pikeman.setSpeed(1);
pikeman.setStrength(5);
pikeman.setHealth(10);
// ...
Pochvala pre každého, kto príde na to, ako urobiť set metódy chainovateľné a nerozbije pri tom kód
Úloha
Pridajte lukostrelcovi (a iba lukostrelcovi) vlastnosť dostrel (range)
archer.range = 5;
archer.setRange = function (newRange) {
this.range = newRange;
};
archer.getRange = function () {
return this.range;
};
var extendByRange = function (unit) {
let range;
const setRange = function (newRange) {
range = newRange;
};
const getRange = function () {
return range;
};
unit.setRange = setRange;
unit.getRange = getRange;
return unit;
};
const archer = unitFactory();
extendByRange(archer);
archer.setRange(4);
Využitie Module Patternu
- skrývanie implementáčných detailov a privátnych vlastností
- ochrana objektov pred narušením zvonka
- umožňuje "komponentové" programovanie
- ochrana pred zaprasením globálneho menného priestoru
Moduly nie sú iba Module Pattern
CommonJS a ES2015 dovoľujú mať pre skripty samostatné menné priestory a exportovať von iba želané premenné.
CommonJS
// index.js
var square = require('./square.js');
console.log('area is ' + square.area(5));
// square.js
var area = function (length) {
return length * length;
};
module.exports = {
area: area
};
ES2015
// index.js
import square from './square';
console.log('area is ' + square.area(5));
// square.js
const area = (length) => {
return length * length;
};
export default {
area
};
Opakovanie
- Privátnosť pre premenné sa v JS dosahuje inak, ako v OOP jazykoch
- Scope je definovaný miestom a spôsobom deklarácie (var, let, const)
- Closure je obálka nad premennými, ku ktorým má funkcia prístup
- IIFE je okamžité zavolanie anonymnej funkcie, robíme to preto, aby sme neprasili globálny menný priestor
- Module Pattern nám umožňuje vytvárať privátne premenné a funkcie
- V JS vieme rozširovať objekty aj po ich vytvorení
Ďakujem za pozornosť
Moduly v JavaScripte
By Milan Herda
Moduly v JavaScripte
- 502