Vydělávej až 160.000 Kč měsíčně! Akreditované rekvalifikační kurzy s garancí práce od 0 Kč. Více informací.
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

3. diel - Funkcie a výnimky v CoffeeScript

Vítam vás u tretieho dielu o jazyku, ktorý šetrí programátorov čas a životnosť klávesnice. Minule bola reč a vetvenia a cykloch. Ako som sľúbil, dnes sa budeme rozprávať o veľmi dôležité časti (nielen) JavaScriptu - funkciách a ich zápisu v CoffeeScriptu.

Úvod do funkcií

Ako sme si ukázali už v prvom dieli, funkcie voláme rovnako ako v JS. Môžeme však vynechať zátvorky (ak má funkcie parameter) a bodkočiarka. Ako ale vytvoriť vlastný funkciu? Na začiatok vám musím povedať dôležitú vec - V CoffeeScriptu nemožno deklarovať pomenované funkcie (function declaration), tj. Žiadny kód v CoffeeScriptu sa nezkompiluje do niečoho takého:

function mojeFunkce() {
  // tělo funkce
}

Dôvodom pre vynechanie tohto spôsobu z CoffeeScriptu je podľa autora problém v starších verziách IE (pre viac informácií si prečítajte FAQ). CoffeeScript umožňuje 'iba' ukladať do premenných funkčnej výrazy (function expression). Ak nutne potrebujete mať deklarovanú funkciu, nezúfajte, môžete jednoducho dať bežný JS kód medzi `` (na anglickej klávesnici znak pod Esc):

# Coffee kód...

`function mojeJSFunkce(x) {
  var vysledek = x / 2;
  return vysledek;
}`

# Coffee kód...

Tieto znaky povedia CoffeeScriptu "Toto nemusíš prekladať, je to normálne JS". Možno som sa mal o tejto vychytávke zmieniť už na začiatku seriálu :)

Späť k funkciám v CoffeeScriptu. Syntax je nasledujúca (pozor na odsadenie tela funkcie):

funkce = ->
  7

JavaScript:

var funkce;
funkce = function() {
  return 7;
};

Všimnite si zaujímavé veci - v CoffeeScript kóde som nenapísal slovíčko return, vo výslednom JS kóde sa však objavilo. V CoffeeScriptu funkcie vždy vracia posledný príkaz. Ak chcete tomuto správaniu zabrániť, stačí jednoducho napísať:

funkce = ->
  console.log 'Nic nevracím'
  return

Najskôr vás napadlo, ako sa CoffeeScript zachová, keď budeme mať vo funkcii vetvenia.

funkce = ->
  r = Math.floor Math.random() * 10 + 1;
  if r < 5
   'menší, než 5'
  else if r > 5
   'větší, než 5'
  else 5

výsledok:

var funkce;

funkce = function() {
  var r;
  r = Math.floor(Math.random() * 10 + 1);
  if (r < 5) {
    return 'menší, než 5';
  } else if (r > 5) {
    return 'větší, než 5';
  } else {
    return 5;
  }
};

Vidíme, že CoffeeScript vracia nielen posledný príkaz celej funkcie, ale tiež posledný príkaz vo vetve.

Funkcie s parametrami, IIFE & splats

Funkcia samozrejme existujú preto, aby spracovali dáta, ktoré im odovzdáme - parametre. Zápis funkcie s dvoma parametrami vyzerá v CoffeeScriptu nasledovne:

funkce = (x, y) ->
 x + y

Parametrom môžete jednoducho nastaviť predvolené hodnoty (ako napr. V PHP):

funkce = (cislo = 10) ->
 alert "Číslo je #{cislo}"

funkce()        # Číslo je 10
funkce 30       # Číslo je 30

JavaScript:

var funkce;

funkce = function(cislo) {
  if (cislo == null) {
    cislo = 10;
  }
  return alert("Číslo je " + cislo);
};

funkce();
funkce(30);

Iste viete, že JS umožňuje bezprostredne vyvolať funkčné výraz (immediately Invoked Function Expression - IIFE) nasledovne:

(function() {return alert('bububu');})();

V CoffeeScriptu možno IIFE zapísať podobne:

(-> alert 'bububu')()

Ale keďže už poznáme slovo do, ktoré volá funkciu, nahradíme ním zátvorky:

do -> alert 'bububu'

V CoffeeScriptu môžeme pomocou tzv. Splats (znamená "plácnutí") jednoducho vytvoriť funkciu, ktorá prijme ľubovoľný počet parametrov:

funkce = (parametry...) ->
  console.log parametr for parametr in parametry

funkce(1, 2, 'tri', ['mam', 'rad', 'kavu'], ['Nescafé', 'Tchibo', 'Starbucks']...)

# 1
# 2
# tri
# ["mam", "rad", "kavu"]
# Nescafé
# Tchibo
# Starbucks

Všimnite si, že splat... možno použiť aj pri volaní funkcie a to spôsobí, že jednotlivé položky poľa sa berú ako samostatné parametre, namiesto aby sa celé pole považovalo za jeden parameter, ako je tomu u pole [ 'mam', 'rád ',' kavu ']. Vo výslednom JS kódu vidíme, že splats sú riešené pomocou objektu arguments:

var funkce,
  __slice = [].slice;

funkce = function() {
  var parametr, parametry, _i, _len, _results;
  parametry = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
  _results = [];
  for (_i = 0, _len = parametry.length; _i < _len; _i++) {
    parametr = parametry[_i];
    _results.push(console.log(parametr));
  }
  return _results;
};

funkce.apply(null, [1, 2, 'tri', ['mam', 'rad', 'kafe']].concat(__slice.call(['Nescafé', 'Tchibo', 'Starbucks'])));

Povedzme, že budeme chcieť vypísať posledný argument pomocou funkcie alert (), jednoducho pridáme ďalší parameter:

funkce = (parametry..., posledni) ->
  console.log parametr for parametr in parametry
  alert "#{posledni} <- tohle je poslední parametr"

Keď použijeme rovnaké pole ako v minulom príklade, posledná hodnota v konzole bude "Tchibo" a vypíše sa nám hláška "Starbucks <- toto je posledná parameter".

Premenné v rôznom rozsahu (scope)

Vám, ktorí v JS programujete už nejaký ten piatok, možno vŕtajú hlavou otázky, ako: "Keď nemôžem deklarovať premennú pomocou var, aké správanie mám očakávať, keď mám vo funkcii a mimo nej premennú s rovnakým menom?", Alebo: "Ako definujú globálnej premennej? ".

Odpoveď na prvú otázku: Ak vo funkcii bude premenná s rovnakým názvom, ako mimo nej, nebude deklarovať lokálne premennú (parametre s rovnakým menom ako vonkajšia premenná sú samozrejme formálne). Toto je rozdiel oproti napr. PHP:

$x = 1;
function f()
{
    $x = 5;
}

echo $x;    # 1
f();
echo $x;    # 1

CoffeeScript:

x = 1
f = ->
 x = 5

alert x         # 1
f()
alert x         # 5

Dávajte si teda pozor, obzvlášť v prípadoch, kedy budete mať niekoľko funkcií vnorených do seba.

Odpoveď na druhú otázku: Musíte ju explicitne priradiť k najvyššiemu objektu v hierarchii (obyčajne window). Ak ste si nainštalovali CoffeeScript, iste ste si všimli, že všetok kompilovaný kód sa vkladá do anonymný funkcie

(function(){
  // vygenerovaný kód
})();

Vďaka týmto vlastnostiam je veľmi ťažké znečisťovať omylom globálny menný priestor, na rozdiel od bežného JS, kde jednoducho zabudnete var a už to ide.

Výnimky

Syntax výnimiek je takmer totožná s tou v JavaScripte, akurát názov výnimky sa nemusia špecifikovať a je vždy pomenovaný _error:

f = (x) ->
 if x is undefined
  throw 'Houstone, máme problém'
 else
  alert x

try
 f()
catch
 alert _error
finally
 alert 'Konec'

JavaScript:

var f;

f = function(x) {
  if (x === void 0) {
    throw 'Houstone, máme problém';
  } else {
    return alert(x);
  }
};

try {
  f();
} catch (_error) {
  alert(_error);
} finally {
  alert('Konec');
}

To by bolo pre tento diel všetko a tešte sa na ten ďalší, budeme totiž preberať OOP.


 

Predchádzajúci článok
Vetvenia a cykly v CoffeeScriptu
Všetky články v sekcii
CoffeeScript
Preskočiť článok
(neodporúčame)
Objektovo orientované programovanie v CoffeeScript
Článok pre vás napísal Yahkem
Avatar
Užívateľské hodnotenie:
Ešte nikto nehodnotil, buď prvý!
...
Aktivity