Autor Zpráva
Suta
Profil
Kód A:
var a = {};

a.parametr = "hodnota parametru";

var b = a.parametr, a = null;


1. Jak v tomto případě pracuje v javascriptu garbage collector? Dojde po provedení kódu skutečně ke zrušení celého objektu v paměti, na nějž odkazuje proměnná a?

2. Jakým způsobem by v praxi měl být psán kód javascriptu, kdy chci uložit pouze několik částí jednoho objektu do jiného objektu a poté první objekt odstranit?

3. Jediné, co mě napadlo, by bylo použití b.toString() nebo něco na ten způsob, abych "zrušil" provázanost, ale zřejmě je to zcestná myšlenka.

4. Nic řádného jsem na tuto tématiku nevygooglil, pokud někdo víte o dobrém článku, napište, prosím, odkaz.

Kód B:
var retezec = "25"; // typeof retezec == "string"
var cislo = +retezec; // typeof cislo == "number"


1. Ví někdo zcela přesně, co probíhá "na pozadí" v tomto případě? Budou v paměti uloženy dva rozličné objekty (jeden s řetězcem a druhý s číslem)? Jaká bude jejich provázanost?

Díky za rady a postřehy.
josefadamcik
Profil
Suta:
1. Jak v tomto případě pracuje v javascriptu garbage collector? Dojde po provedení kódu skutečně ke zrušení celého objektu v paměti, na nějž odkazuje proměnná a?

Ano, doje ke zrušení celého objektu, na který odkazuje a. Je potřeba ale správně vyložit pojem celý objekt :)

Řetězec, na který odkazuje vlastnost "parametr" objektu a, je v podstatě dalším objektem, ke kterému se chová GC, stejně jako ke kterémukoliv jinému (tedy bude odstraněn, až když na něj nebude existovat žádná "živá" reference). Vzhledem k tomu, že řetězec je odkazován proměnnou b, která je vytvořena v globálním oboru platnosti a tudíž platná, nebude místo zabrané řetězcem v paměti uvolněno.

2. Jakým způsobem by v praxi měl být psán kód javascriptu, kdy chci uložit pouze několik částí jednoho objektu do jiného objektu a poté první objekt odstranit?
V podstatě tak, jak uvádíte v ukázce.


3. Jediné, co mě napadlo, by bylo použití b.toString() nebo něco na ten způsob, abych "zrušil" provázanost, ale zřejmě je to zcestná myšlenka.

Hlavně řešíte problém, který nemáte. Řetězec v paměti uchovat chcete, proto si přeci vytváříte proměnnou b. Nexistuje důvod, proš nutit interpret JS, aby fyzicky alokoval novou paměť a zkopíroval řetězec na nové místo.

> „1. Ví někdo zcela přesně, co probíhá "na pozadí" v tomto případě? Budou v paměti uloženy dva rozličné objekty (jeden s řetězcem a druhý s číslem)? Jaká bude jejich provázanost?

Asi trochu zjednodušeně, ale případné nepřesnosti určitě někdo rád opraví.) Pozn: vynechávám z úvahy variable hoisting, který výsledek z pohledu vašich otázek nijak neovlivní.

1) alokuje se pamět pro řetězec "25"
2) identifikátru "retezec" je prirazen odkaz na nově alokovaný řetězec
3) operátor + si vynutí konverzi hodnotu odkazovanou identifikátorem "retezec" na typ number => alokuje se nová pamět pro číslo, uloží se do ní převedená hodnota.
4) identifikátoru "cislo" je přiřazen odkaz na nově alokovanou číselnou hodnotu 25

Provázanost obou proměnných není tedy vůbec žádná.
_es
Profil
Textový reťazec v JS nie je objektom.
To, ako rieši kopírovanie a iné veci textových reťazcov interpréter JS, je jeho vnútorná záležitosť.
Suta
Profil
josefadamcik:
Díky. Dá se nějakým způsobem vykonstruovat všeobecné pravidlo, kdy objekty javascriptu rušit ručně a kdy jejich odstranění z paměti nechat na prohlížeči? Konkrétně tím myslím např.: "Lokální proměnné použité ve funkci by vždy/nikdy měly/neměly být v závěru funkce ručně zrušeny" ... ?

Pozn.: jedná se mi o náročnější editor v javascriptu, proto hledám "zdroje", u jednoduchého scriptu s několika objekty bych se s jejich rušením vůbec netrápil.

Dotaz 2: je možné/nepřípustné řešit dynamicky zrušení vnořených prvků ve stránce nastavením vlastnosti innerHTML jejich rodiči? K čemu přesně dojde? Nebo je třeba vždy projít všechny potomky a odstanit je pomocí removeChild?

Díky všem za připomínky a radu.
_es
Profil
Suta:
Dá se nějakým způsobem vykonstruovat všeobecné pravidlo
Existuje jednoduché pravidlo:
Ak k objektu, či iným dátam v JS, nie je v JS možný prístup, tak sú pripravené k zmazaniu.
Prehliadač ich však nemusí mazať, uvoľňovať pamäť, hneď - záleží to od prehliadača.

je možné/nepřípustné řešit dynamicky zrušení vnořených prvků ve stránce nastavením vlastnosti innerHTML jejich rodiči?
Myslím, že to je prípustné, no záleží od prehliadača, ako si potom poradí s prípadnými odkazmi na neexistujúce elementy.
Chamurappi
Profil
Reaguji na Sutu:
kdy objekty javascriptu rušit ručně a kdy jejich odstranění z paměti nechat na prohlížeči?
Ručně je zrušit v podstatě nemůžeš, tak či tak si o osudu rozhodne prohlížeč.

tím myslím např.: "Lokální proměnné použité ve funkci by vždy/nikdy měly/neměly být v závěru funkce ručně zrušeny" … ?
Pokud z té funkce nečouhají do budoucna nějaké další akce definované lokálními funkcemi (např. nastavené události), tak lokální proměnné zrušeny budou, nehledě na to, co do nich nastavíš. Provádět dodatečný úklid obecně není nutné, právě kvůli tomu existuje ten garbage collector…

je možné/nepřípustné řešit dynamicky zrušení vnořených prvků ve stránce nastavením vlastnosti innerHTML jejich rodiči?
Pokud jsou na ty prvky uvnitř navěšeny nějaké vlastní vlastnosti či funkce, můžou v některých prohlížečích uvíznout v paměti, pokud je předem nesmažeš deletem. Na způsobu vyhození potomků už nezáleží (tedy nemělo by záležet).


Reaguji na _es:
Textový reťazec v JS nie je objektom.
Jak to myslíš?

záleží od prehliadača, ako si potom poradí s prípadnými odkazmi na neexistujúce elementy
Nepřestanou existovat. Stejně jako při použití removeChild na ně může pořád existovat nějaká reference, i když již nejsou součástí documentu. Teď jsem provedl pár pokusů a zjistil jsem, že při přepsání innerHTML Explorer smaže innerHTML i v těch odstraněných potomcích, ostatní prohlížeče ne.
_es
Profil
Chamurappi:
Reaguji na _es:
„Textový reťazec v JS nie je objektom.“
Jak to myslíš?
Že objektu sa dajú vytvoriť nové vlastnosti a to sa u textového reťazca nedá:
var o = {};
var s = "abcd";
o.v = 1;
s.v = 1;
alert(o.v) // 1
alert(s.v) // undefined
Alebo pri porovnaní:
var a = "abc", b = "abc";
var x = {}, y = {};
alert(a === b); // true
alert(x === y); // false
V piatom riadku prvého kódu v [#1] je vlastne jedno, či sa kopíruje nejaký pointer alebo celý reťazec, lebo ten reťazec je aj tak nemenný.
Witiko
Profil
_es:
Objekt to je, jelikož dědí funkce od String. Výše popisované chování dokazuje jen, že se v javascriptu zachází se String, Number etc. jako se základním datovým typem a ne jako s referenčním datovým typem. Předává se rovnou "obsah" objektu namísto pointeru na reprezentaci objektu v paměti.

Na rozdíl od jiných objektů má pisatel v javascriptu k objektům Number a String výše-úrovňový přístup. Může editovat jen hodnotu, kterou objekt reprezentuje, ale způsob, jakým se pak kolem dané hodnoty utvoří objekt, neovlivňuje a je čistě na prohlížeči.
_es
Profil
Witiko:
Objekt to je, jelikož dědí funkce od String
Nie je to object.
var x = new String("abcd") // toto je objekt String
var y = "abcd" // toto nie je objekt
var a = new Number(7) // toto je objekt Number
var b = 7 // toto nie je objekt

Výše popisované chování dokazuje jen, že se v javascriptu zachází se String, Number etc. jako se základním datovým typem
Ale string (s malým s) naozaj je neobjektový základný dátový typ.
Objekt String (s veľkým S) je druh objektu.
Objekty x a a z toho kódu sa dajú vo všetkom použiť ako objekty, napríklad vytvoriť vlastnú vlastnosť len toho objektu. To nejde pri premenných y a b. Tak isto porovnávanie pre x a a bude fungovať ako pri ostatných objektoch.
Witiko
Profil
_es:
Netvrdil bych, že jde o neobjektový datový typ, má pouze budit tu iluzi. I number s malým en a string s malým _es dědí metody od String.prototype a Number.prototype. Viz.:

(123).toString();
"abcd".charAt(0);

(123).prototype == new Number(123).prototype;
"abcd".prototype == new String("abcd").prototype;


Rozdíl mezi String a string je spíše ze strany syntaxe předkládané javascriptem.

Přestavme si pro účely příkladu, že řetězec je na straně prohlížeče reprezentován objektem (to není zase tak hypotetické, vzhledem k tomu, že na nízké úrovni stejně musíme jakýkoliv datový typ krom základních typu int, char, atp. reprezentovat objektem), jenž má atribut value obsahující daný text (to je hypotetické, nízkoúrovňové jazyky ne-vždy poskytují základní typ pro řetězec).

Na co by poté hypoteticky obsahovala proměnná obsahující daný řetězec:
String // <-- Na objekt samotný odkazuje new String("aaa")
 - ... atributy ...
 - value = "aaa" // <-- Na atribut objektu odkazuje "aaa"
 - ... další atributy ...


Se zápisem new String("text") se ukládá do proměnné odkaz na instanci objektu. Se zápisem "text" se ukládají do proměnné jenom daná data, kolem kterých se ale poté stejně utvoří objekt (viz.: "aaa".prototype == new String("aaa").prototype -> true).

Rozdíl je v tom, že v prvním případě pak proměnná obsahuje pointer na objekt, zatímco v druhém případě "obsahuje" pouze hodnotu našeho výše definovaného hypotetického atributu value - s tím, že má přístup i k veškerým metodám kolem hodnoty se utvořivší instance objektu String, což ze stringu dělá svým způsobem hybrida. Stejně tak, jako String, ačkoliv se jedná o objekt, navrací text (podobně jako Array nebo RegExp navracejí text a mají speciální způsoby definice pevně v syntaxi) - jedná se o nestandardní chování, které u vlastních objektů v JavaScriptu co já vím není možné replikovat.

C++ zápisem by nejspíš platilo, že: new String() == &string, tento zápis ale opět ignoruje to, co jsem zmiňoval v minulém odstavci: Zapuštěnost základních objektů a datových typů do syntaxe JavaScriptu a tím vzniknuvší odchylky od způsobu, jakým by se objekty a datové typy měly chovat.
_es
Profil
Witiko:
I string s malým s a number s malým n dědí metody od String.prototype a Number.prototype.
Nie, nič sa nededí.
Pri použití operátora „bodka“ dochádza k dočasnému vytvoreniu objektu String alebo Number.
To však neznamená, že hodnoty, na ktoré sa používa ten operátor, sú naozaj objekty. Je to vidno v [#7], kde je vlastnosť v pridaná len do dočasného objektu a hneď potom zaniká spolu s tým objektom.
JS tak isto pri niektorých operáciách automaticky číslo prevádza na textový reťazec. To však ešte neznamená, že číslo naozaj je textovým reťazcom.

Rozdíl mezi String a string je spíše ze strany syntaxe.
Sú to odlišné dátové typy.
Witiko
Profil
_es:
Sú to odlišné dátové typy.
Tím způsobem, jakým nám je podává JavaScript ano. Na straně interpretera se jedná o jedno a to samé, jen v jednom případě se s textem zachází jako s objektem a v druhém jako se základním datovým typem, ačkoliv pod pokličkou (čti: na straně interpretera) je to samozřejmě také objekt.

Pri použití operátora ‚bodka‘ dochádza k dočasnému vytvoreniu objektu String alebo Number.
Na úrovni JavaScriptu možná. Ve skutečnosti se jedná o objekt celou dobu, mění se jen způsob, jakým jej JavaScriptový interpret prezentuje.

V chování, které interpret zprostředkovává je samozřejmě hlavní a zásadní rozdíl a to ten, že v jednom případě se s objektem pracuje jako s referenčním typem, přičemž na proměnnou "je přilepen" pointer a v druhém případě dochází k neustálému klonování a replikaci objektu.

To, že ho tak javascript definuje, neznamená, že v jazyce, ve kterém je interpret napsán, je možné definovat řetězec bez použití objektů.
_es
Profil
Witiko:
pod pokličkou (čti: na straně interpretera) je to samozřejmě také objekt.
Čím je charakterizovaný ten „objekt pod pokličkou“? Ako sa majú obyčajné reťazce správať, je popísané v špecifikácii ECMA scriptu - že sú to neobjektové dátové typy. Či si interpréter pri ich kopírovaní v JS kopíruje pointery alebo celé reťazce, alebo raz tak a raz inak, je jeho záležitosť.

Witiko:
Ve skutečnosti se jedná o objekt celou dobu, mění se jen způsob, jakým jej JavaScriptový interpret prezentuje.
To by sa ale potom v [#7] v 6. riadku prvého kódu nezobrazilo undefined. Objekt sa vytvorí len v 4. riadku a ihneď je „zahodený“. Premenná s v tom kóde objekt neobsahuje. Ak by sa namiesto obyčajného reťazca "abcd" do premennej s priradil objekt typu String (ako v [#9]), tak by sa v 6. riadku nezobrazilo undefined.
Witiko
Profil
_es:
To by sa ale potom v [#7] v 6. riadku prvého kódu nezobrazilo undefined.
Myslím, že v tom jsme se shodnuli. string skutečně není ze strany JavaScriptu brán jako objekt (mé tvrzení „Ve skutečnosti se jedná o objekt celou dobu...“ se vztahovalo k interpretu, ne JavaScriptu), přesto však věřím tomu, že je takříkajíc objektem obalen. Proměnná obsahující data typu "string" odkazuje na hodnotu objektu String. Vztah bych si přestavoval nějak takto:

function String(string) {
  this.value = string;
}


Kdyby se základní objekty v JavaScriptu držely pravidel, která jsou stanovena pro custom objekty, pak by:

Proměnná obsahující objekt typu String nenavracela string v něm zabalený, ale text [object String]
Proměnná obsahující datový typ string neměla přístup k funkcím objektu String a při potřebě pracovat s nimi by muselo dojít k ručnímu vytvoření nové instance objektu.

A ano, nejspíš by to bylo poměrně nepohodlné.
_es
Profil
Witiko:
mé tvrzení ‚Ve skutečnosti se jedná o objekt celou dobu…‘ se vztahovalo k interpretu, ne JavaScriptu
Ale ako prehliadač, či jeho interpréter/kompilátor JS vnútorne, „pod pokrievkou“, pracuje, je len špekulácia. Podstatná je špecifikácia programovacieho jazyka.

Proměnná obsahující objekt typu String nenavracela string v něm zabalený, ale text [object String]
To sa dá zmeniť pomocou:
String.prototype.toString = NejakáFunkcia1;
String.prototype.valueOf = NejakáFunkcia2;
Witiko
Profil
_es:
To sa dá zmeniť pomocou:
Ha! Most spectacular. Netušil jsem, že máme u Objektů k dispozici takovéhle hračky (čti rezervované funkce), to může být potenciálně velice užitečné! :-)
Respektive tušil, ale nikdy jsem myšlenky tím směrem dále nerozvíjel.

Vaše odpověď

Mohlo by se hodit

Neumíte-li správně určit příčinu chyby, vkládejte odkazy na živé ukázky.
Užíváte-li nějakou cizí knihovnu, ukažte odpovídajícím, kde jste ji vzali.

Užitečné odkazy:

Prosím používejte diakritiku a interpunkci.

Ochrana proti spamu. Napište prosím číslo dvě-sta čtyřicet-sedm: