CoffeeScript: nový jazyk, nové chytáky
CoffeeScript vzbudil mezi vývojáři webových aplikací slušný zájem, mnozí si pochvalují jeho vyjadřovací schopnosti a eleganci. Přesto má CoffeeScript, jako každý jazyk, kromě příjemných překvapení i některé záludnosti a tajemná zákoutí, do nichž může nepřipravený vývojář snadno padnout.
CoffeeScript je velmi mladý jazyk. Vývojářům ještě nenabízí vyspělý ekosystém (například debuggery), ani s literaturou to není tak úplně slavné a vědění se šíří zatím převážně v diskusních fórech a na Twitteru. První skutečná kniha, která vyšla na téma CoffeeScript, byla vydána nakladatelstvím Pragmatic Programmers, jmenuje se CoffeeScript: Accelerated JavaScript Development a autorem je Trevor Burnham.
V této knize naleznete nejen informace o programování v CoffeeScriptu či praktické rady (jak instalovat, jak debuggovat, kde nalézt vhodné pluginy pro editory), ale i upozornění na některá úskalí, která CoffeeScript (potažmo JavaScript) přináší, stejně jako tipy a triky, které vám používání CoffeeScriptu zpříjemní. V dalším textu se na některá taková tajemství, probíraná ve zmíněné knize, podíváme.
Když na mezeře záleží…
Z většiny programovacích jazyků jsme zvyklí, že na nějaké té mezeře většinou nezáleží. V JavaScriptu například není rozdíl mezi těmito dvěma zápisy:
var prefix = "#prvek_"; // zápis 1 var id1 = prefix + 12; // zápis 2 - jedna mezera chybí var id2 = prefix +12;
V CoffeeScriptu bude rozdíl významný:
prefix = "#prvek_" id1 = prefix + 12 # == #prvek_12 id2 = prefix +12 # TypeError
Proč? Vzpomeňme na to, že Coffeescript umožňuje zapsat volání funkcí bez závorek. Poslední řádek tak bude přeložen jako
var id2 = prefix(+12);
což je něco jiného, než jsme zamýšleli.
Stejně tak může problémy způsobit fakt, že toto vyhodnocování operátorů je asociativní zprava, takže konstrukce
console.log (fn 3, fn 4)
vypíše pouze výsledek volání funkce fn(3). Kompiler totiž vyhodnotí zápis jako:
console.log (fn (3, fn (4)))
tedy zase opět něco zcela jiného.
Doporučení: parametry vnořených volání funkcí pište do závorek; vynechat je můžete pouze u volání nejvyšší úrovně. Tedy: console.log fn(3), fn(4).
Pozor na mezeru mezi jménem funkce a závorkou: console.log fn (3), fn (4) bude vyhodnocena opět jinak – tím výše zmíněným způsobem, tedy jako vnořené volání funkce fn!
Scope – oblast viditelnosti
Záhadné chyby může způsobit implicitní pravidlo oboru platnosti proměnných. Proměnné se v Coffeescriptu nedefinují explicitně, ale využívají se tři pravidla:
- Funkce vytváří oblast viditelnosti (scope), a jediný způsob, jak vytvořit oblast viditelnosti, je definice funkce.
- Proměnná je viditelná v oblasti nejvyšší úrovně, kde jí byla přiřazena hodnota.
- Mimo scope není proměnná viditelná.
Jak ukazuje Trevor Burnham v kapitole 2.2, přináší to někdy podivuhodné konsekvence:
x = 42 init = -> x = 0 init() console.log x
Výsledek bude nula, protože definice funkce na řádku 2 vyhodnotí x jako globální proměnnou (resp. existující v nadřazeném scope). Co způsobí prohození řádků 1 a 2?
init = -> x = 0 x = 42 init() console.log x
Tentokrát bude výsledek 42, protože v okamžiku definice funkce (na řádku 1) bude x neznámé, a bude vyhodnoceno tedy jako lokální proměnná viditelná pouze ve funkci init.
Je to logické a vyplývá to z pravidel viditelnosti proměnných v CoffeeScriptu, přesto to dokáže zaskočit. A aby nebylo zmatků dost: pokud má funkce parametr, pojmenovaný stejně jako „globální“ proměnná (správně: jako proměnná v nadřazeném scope), bude v těle funkce rovněž lokální. Upravíme první příklad:
x = 42 triple = (x) -> x * 3 console.log triple x console.log x
V těle funkce triple bude proměnná x tentokrát lokální!
== a ===
V JavaScriptu je zásadní rozdíl mezi operátory == a ===. Viz lehce upravený příklad z WTFJS:
var a = 0, b = '', c = '0'; a == b; // true a == c; // true b == c; // false
Matematik by řekl, že operátor == není tranzitivní. CoffeeScript v tomto ohledu lehce programátorovi pomůže: pokud zapíšete ==, přeloží ho jako ===. Jak v CoffeeScriptu ale zapíšete ekvivalent JS operátoru ==? Odpověď: Nijak. Vždy se porovnává typově.
key:value
Představme si definici objektu:
x = 10
y = 20
radius = 5
kruh = {x: x, y: y, radius: radius}
CoffeeScript má pro případy, kdy se vlastnost jmenuje stejně jako proměnná, která je přiřazována, zkratku. Poslední řádek lze tedy zapsat i takto:
kruh = {x, y, radius}
Ovšem CoffeeScript jde ještě o kousek dál. Vzpomínáte na „destrukturované přiřazení“?
pole = [10, 20] [a, b] = pole
Stejným způsobem lze přiřadit i vlastnosti objektů:
{x: mojeX, y: mojeY} = kruh
A opět: pokud se vlastnost jmenuje stejně jako proměnná, do níž bude přiřazováno, lze zkrátit:
{x, y} = kruh
Autor uvádí i příklad při vývoji pro Node.js – píšete testy a potřebujete metody assert.ok a assert.strictEqual. Můžete použít konstrukci:
{ok, strictEqual} = require "assert"
a budete mít obě metody dostupné v proměnných ok a strictEqual.
Destrukturované přiřazení lze zapsat i vnořené – parsování dat v JSON je pak lahůdka:
{result: [code, text]} = serverResponse
Když super() není super
CoffeeScript usnadňuje i psaní tříd „běžným“ způsobem (a odstiňuje tak programátora od zapeklitostí prototypové dědičnosti). K volání metod předka pak používá obvyklé volání metody super().
class Vyrobek constructor: (zaruka) -> DBzaruk.save(this) if zaruka class Toaster extends Vyrobek constructor: (zaruka) -> super()
V takovémhle případě je volání metody rodičovské třídy chybně – nepředáme parametr zaruka. Můžeme napsat super(zaruka), ale CoffeeScript má (opět) pohodlnější zkratku:
class Toaster extends Vyrobek constructor: (zaruka) -> super
Takto zapsáno zavolá stejnojmennou metodu rodičovské třídy se všemi parametry.
A dál…?
CoffeeScript představuje pro vývojáře novou neprobádanou oblast, kde je možné za každým rohem narazit na zajímavou možnost, která vám ulehčí práci – ovšem taky můžete narazit i v místech, kde si jste jistí, že přesně víte, co děláte. Doufejme, že tento článek alespoň trochu osvětlil některá potenciálně nebezpečná zákoutí a ušetřil vám krušné chvíle při ladění.
Školení: Návrh a používání MySQL databáze

Naučte se používat jednu z nejrozšířenějších databází. Dozvíte se vše potřebné od návrhu až po samotné využití MySQL v projektech.
Školení pro všechny, kteří se chtějí naučit efektivně pracovat s MySQL nebo se v práci s touto databází zlepšit.
Přihláška a podrobné informace
Přehled názorů
Tento text je již více než dva měsíce starý. Chcete-li na něj reagovat v diskusi, pravděpodobně vám již nikdo neodpoví. Pro řešení aktuálních problémů doporučujeme využít naše diskusní fórum.