Slovník | Vyhledávání | Mapa webu
 
Základy informatiky pro biologyAlgoritmizace a programování Programování v JavaScriptu - II Funkce Platnost proměnných a closures (uzávěry)

Logo Matematická biologie

Platnost proměnných a closures (uzávěry)

JavaScript na rozdíl od jiných jazyků nemá příliš propracovaný systém programových bloků, ale v jednoduchosti je síla. Jelikož zde nejsou žádné jmenné prostory, žádné třídy ani nic podobného, základní jednotkou oboru platnosti proměnných je funkce (kromě funkce je zde také globální prostor jmen).

Jelikož se mohou funkce zanořovat (tj. lze definovat funkci uvnitř těla jiné funkce), každá taková zanořená funkce má dostupné všechny proměnné, které jsou dostupné z funkce nadřazené.

var d = 8;
var foo = function () {
    var a = 1, b = 2;

    // a = 1, b = 2, d = 8
    d = 10;
    // a = 1, b = 2, d = 10

    var bar = function () {
        var b = 1, c = 8

        // a = 1, b = 1, c = 8, d = 10
        a = 5;
        b = 3;
        d = 20;

        // a = 5, b = 3, c = 8, d = 20
    };
    bar();

    alert("a = " + a); // a = 5
    alert("b = " + b); // b = 2
                       // c neexistuje
};

foo();

alert("d = " + d); // d = 20

S vědomím tohoto se dají vyrábět tzv. closures, což jsou funkce, které v sobě obsahují kontext z jiné funkce, ve které byly definované, i když vykonávání jejich „mateřské“ funkce už skončilo. Nejlépe to budeme demonstrovat na příkladu. Řekněme, že potřebujeme objekt reprezentující osobu. Jelikož lidé mohou růst, bude zde samozřejmě možnost postupně časem měnit výšku takové osoby. První řešení, jaké by nás mohlo napadnout, by mohlo vypadat takto:

var person = function (meters) {
    this.height = meters;
};

Osobu vytvoříme voláním funkce person() s operátorem new (aby se vytvořil nový objekt, který bude přiřazen do this). K výšce můžeme po vytvoření přistupovat pomocí vlastnosti height. Je to velice jednoduché, ale je zde problém, že výšku nemůžeme nijak regulovat. Takže se nám zde pak klidně může vyskytnout osoba měřící místo pár metrů i pár stovek (kilo)metrů, ba dokonce i nějaká, která by „rostla do země“ (výška by byla záporná), či osoba nulového vzrůstu. Dalším řešením by mohlo být zavedení tzv. „getterů“ a „setterů“, takže by stačilo přidat:

person.prototype.getHeight = function () {
    return this.height;
};

person.prototype.setHeight = function (meters) {
    if (meters > 0 && meters < 5) {
        this.height = meters;
        return true;
    }
    return false;
};

Mohlo by se zdát, že problém je vyřešen, ale jelikož JavaScript nezná žádnou viditelnost vlastností objektů, pořád můžeme měnit výšku i jinak než přes její setter – stačí normálně změnit vlastnost height. Řešením jsou closures.

var person = function (meters) {
    this.getHeight = function () {
        return meters;
    };

    this.setHeight = function (new_meters) {
        if (new_meters > 0 && new_meters < 5) {
            meters = new_meters;
            return true;
        }
        return false;
    };
};

Nyní se již nemůžeme k výšce dostat jinak než pomocí getteru a setteru.

 
vytvořil Institut biostatistiky a analýz Lékařské fakulty Masarykovy univerzity