Autor Zpráva
anoim
Ahoj,
četl jsem nějaké články o anonymních funkcích a uzávěrech a mám pocit jak kdyby ty informace byli protichůdné. Nebo jen nejasná formulace, že v tom teď mám bordel. Např. na Wikipedii jsem našel tuto formulaci, kde mi splývá v jedno anonymní, vnitřní funkce a uzávěr že teď nevím co je co:

Anonymní(vnitřní) funkce a uzávěry (closures)
Vnitřní funkce (neboli funkce definované uvnitř jiných (vnějších) funkcí) jsou vytvořeny při každém zavolání funkce nadřazené, a proměnné funkcí vnějších existují po dobu existence funkce vnitřní, dokonce i po ukončení zvolání (tedy i po navrácení této vnitřní funkce, má daná funkce stále přístup k proměnným své funkce vnější) – toto je mechanismus v JavaScriptu nazývaný jako closures - uzávěry.

V jiném článku jsem zase četl, že anonymní funkce je funkce, která je definovaná nebo volaná bez identifikátoru. Anonymní funkce jsou deklarovány pomocí operátoru funkce. Operátor funkce, můžete použít k vytvoření nové funkce.

Tak teď nevím jestli každá funkce která používá operátor je anonymní? A co tím operátorem bylo myšleno jestli klíčove slovo function nebo závorky ()? Jestli tedy skutečně anonymní funkce jsou pouze ty, které se nachází uvnitř jiné funkce. Taky se mi zdá, že ta definice z vyky není přesná, že tam schází, že tam musí být ta deklarace var myname = function ... Můžete mi tedy tyto věci potvrdit nebo vyvrátit? A ještě k těm uzávěrům. Znamená to, že anonymní funkce = uzávěr? Protože tak jsem to z Wiki pochopil, že vnitřní == anonymní funkce == uzávěr ... a tj. vnější funkce si uchovává proměnné i po skončení funkce. A nejsem si jistý, zda se proměnné z vnější dědí i to té vnitřní.

Dík za ujasnění.
Witiko
Člen
function a() {
  var a = 1;
  function b() {
    function c() {
      alert(a);
    }
  c();
  }
b();
}

a(); //1


Anonymní funkce = lokální funkce beze jména. Lokální proměnné a argumenty dané funkce jsou přístupné ze všech vytvořených anonymních funkcí. Lokální proměnné anonymních funkcí však nejsou přístupné z nadřazených funkcí, viz.:

function a() {
  function b() {
    var a = 1;
  }
  b();
  if(a) alert(a); // lokální proměnná a ve funkci a neexistuje
}


To však neznamená, že nelze měnit lokální proměnné funkce nadřazené.

function a() {
  var a = 1;
  function b() {
    a = 2;
  }
  b();
  alert(a); // 2
}


Operátor deklarace funkce, alias klíčové slovo je function stejně jako var je klíčové slovo deklarace proměnné.
Rozdíl mezi:

var a = function() {}

a

function a() {}


by být neměl, ale nechám se klidně opravit.

Uzávěry jsou výborné například i u tvorby prototypů. Konstruktor prototypu je funkce a proto si lze definovat privátní proměnné objektu ke kterým mohou přistupovat jen funkce objektu.

Řešení přidávání skóre bez uzávěru s veřejnou proměnnou:

var Score = function() {
  this.score = 0;
}
Score.prototype.increase = function(amount) {
  this.score += amount;
}


Pokud není důvod, aby byla proměnná veřejná a šla zevně editovat, je toto řešení lepší:

var Score = function() {
  var score = 0;
  this.increase = function(amount) {
    score += amount;
  }
}


this.increase je v tomto případě anonymní funkce, ačkoliv je veřejná.

V této ukázce je increase anonymní privátní zevně objektu nepřístupná funkce:
var Score = function() {
  var score = 0;
  var increase = function(amount) {
    score += amount;
  }
  this.plusDeset = function() {
    increase(10);
  }
}
anoim
Witiko:
Tak nejdříve se vyjádřím k začátku (o uzávěrech jsem zatím nečet, přečtu později).

Jaký má vlastně smysl vytvářet ty funkce tak jak to děláš ty, tj. do jedné funkce vytvoříš další funkci, do ní další a do ní zase další? Má to nějakou výhodu? Jinak jsem teda pochopil ze článkům že tento příklad by bylo kratší realizovat tak, že by se ty funkce vložili jako argument, ale to teď rozebírat nechci (na to je ještě čas než to pochopím).

Takže z prvního příkladu jsem pochopil, že když se pokusím volat anonymní funkci c() z nadřazené funkce, tak se nedovolám, protože je to uvnitř anonymní funkce. Pak asi ale nechápu přesně to slovo lokální - není to relativní? Myslíš lokální, jako místní, tj. pouze ta jedna úroveň, kterou mám zrovna namysli, a , b nebo c. Pak jsou tedy všechny tři funkce anonymní, chápu to už konečně správně? Anebo se pletu, protože pokud platí že globální proměnné se deklarují na nejvyšší úrovni skriptu, tak tedy ta první funkce je globální, přístupná odkudkoliv, kdežto ty ostatní, které jsou uvnitř jsou anonymní. Ale kdybych je zkusil předem deklarovat jako globální, nezměnilo by se to?

var b;
var c;

function a() {
  var a = 1;
  function b() {
    function c() {
      alert(a);
    }
  }
c();
}

Hm. Nefunguje. Tak asi ne...


Takže k té větě co jsem někde vyčetl - že anonymní funkce "je funkce, která je definovaná nebo volaná bez identifikátoru." - tak to není pravda?
Witiko
Člen
Tak já to rozepíšu:

function a() {
  var a = 1; // definuji lokální proměnnou a
  function b() { // definuji lokální funkci b, která je vnořená do funkce a a má přístup k jejím argumentům a lokálním proměnným
    function c() { // definuji lokální funkci c, která je vnořená do funkce b a tím pádem i a a má přístup k jejím argumentům a lokálním proměnným
      alert(a); // pomocí alert() vypíšu lokální proměnnou a.
    }
  c();
  }
b();
}

// funkce b a c jsou lokální a jsou unikátní pro každé volání funkce. Mimo funkci neexistují - tzn. chovají se stejně jako lokální proměnné
// příklad má demonstrovat, že lokální funkce dědí lokální proměnné konstrukce ve které byla definována

a(); //1


anonymní funkce "je funkce, která je definovaná nebo volaná bez identifikátoru."
Anonymní funkce je název pro funkci lokální, která nemá žádné jméno. Řekněme, že předáš funkci setTimeout callback jako anonymní funkci:

setTimeout(function(){
  alert("a");
},1000)


Daná funkce nemá jméno, je definována přímo na místě použití, je proto anonymní. Co se funkciality týče, neliší se od funkce lokální, tu však deklarujeme se jménem a většinou ji použijeme vícekrát. Učebnicový příklad anonymní funkce je vyhodnocení výrazu na místě:

// anonymní funkce:

alert((function() {
  return 1+1;
})());


Výše zmíněná funkce nemá příliš praktických využití, ale chápeš co tím myslím.
anoim
Poslední dva příklady chápu zcela jasně. Tam to jméno opravdu není. alert("a"). U toho prvního příkladu to bereš tak, že anonymní funkce je ta, která není přístupná z vnějšího prostředí? Čili je lokální. Protože všechny tři funkce mají jméno a, b, c . Ale rozdíl je v tom, že z nejvyšší úrovně skriptu se dovoláš jen a.
anoim
Dívám se, že ještě nerozumím tomu, proč u posledního příkladu jsou uvnitř funkce alert ty první závorky? Když je smažu tak se nic nestane:

alert(function() {
return 1+1;
}());

Teď jsem si vzpomněl, že () je operátor volání funkce, tak snad proto?
anoim
Tak už je mi to jasný, takže anonymní funkce, vnitřní funkce, lokální funkce a uzávěra je vše jedno a to samé. Tak dík za ochotu
Witiko
Člen
Vlastně ano, anonymní funkce je název pro lokální funkci, která nemá jméno. :) Rádo se stalo
habendorf
Člen
Witiko to zde popsal tak hezky, že bych link na toto vlákno navrhoval přidat sem: http://diskuse.jakpsatweb.cz/?action=vthread&forum=8&topic=106539, konkrétně do 3. bodu.
anoim
Ještě jednu podstatnou věc si zapomněl zmínit (našel jsem zas na netu).

function say667() {
  var num = 666; // local
  var sayAlert = function() { 
  alert(num); // reference to local variable
  }
  num++;
  return sayAlert;
} 
var a = say667();
a();


Lokální proměnné se uchovávají jako odkaz, nikoliv jako kopie. Tady ten proces mi přijde dost zvláštní a nejsem si jist zda chápu co se v tomto příkladě děje. Nejdříve se vypočítá hodnota num v nadřazené funkci a pak se teprve spustí funkce sayAlert?
anoim
Ještě jsem narazil na internetu na velice zajímavý komentář od Richarda Cornforda
Odkaz
Který upozorňuje na riziko anonymních funkcí při přiřazování vlastnostem objektů, že to může být nebezpečné z hlediska paměti.

The function expression option (3) is probably the easiest to write but
its drawback comes form the fact that function expressions are often
(usually) also inner functions and assigning them to properties of DOM
elements can induce the IE memory leak problem because of the closure
formed by the assignment. (lots of ways of avoiding that or negating the
harmful effects.)

It is also possible for the function referenced in the first approach to be an inner function, producing the same risks as the function expressions on IE. But usually the function referenced would be defined as a global function and that problem would not arise.

(Zapomenuté heslo?)

Vaše odpověď

Prosím používejte diakritiku a interpunkci.

Ochrana proti spamu. Napište prosím číslo dvacet-čtyři: