Kirjautuminen

Haku

Tehtävät

Keskustelu: Nettisivujen teko: JS: x.y is not a function

Sivun loppuun

Paulus M [26.05.2009 15:08:18]

#

en ole taas pitkään aikaa vääntänyt JS:ää ja en millään keksi, että mikä on ongelma:

<script language = "javascript">

function Animaattori(animlkm)
{
	var animaatiolkm = animlkm;
	var animAlustettu = 0;
	var animaatiot = new Array(animlkm);

}

function uusiAnimaatio(nimi, framelkm)
{
	this.animaatiot[this.animAlustettu] = new Array(framelkm);
	for(var i = 0; i < framelkm; i++)
	{
		this.animaatiot[this.animAlustettu][i] = nimi +String(i);
	}


	this.animAlusettu++;
}

function ajaAnimaatio(animlkm)
{


}

animator = new Animaattori();

for(var i = 0; i < 10; i++)
{
	animator.uusiAnimaatio("kuva", 15); //VIRHE SIJAITSEE TÄSSÄ

}

for(var b = 0 ; b < 10; b++)
{
	for(f = 0; f < 15; f++)
	{
		document.write(' testi ');
		document.write(animator.animaatiot[b][f]);
	}
}

</script>

Firefoxin virheilmoitus:

Virhe: animator.uusiAnimaatio is not a function
Lähdetiedosto: file:///C:/Documents%20and%20Settings/IBM/Omat­%20tiedostot/kotisivut/testi.html
Rivi: 39

punppis [27.05.2009 00:01:19]

#

Yrität käyttää nyt funktioita luokkina.

jlaire [27.05.2009 05:11:51]

#

Ilmeisesti yrität laittaa kuvien nimiä kaksiulotteiseen taulukkoon. Ongelma on se, että koodissa ei ole järkeä. Olioita ei tarvitse eikä kannata käyttää joka paikassa, varsinkaan jos ei ollenkaan ymmärrä kielen oliosysteemiä. Itse lähtisin jostain tällaisesta liikkeelle:

var imgs = [];

function add_animation(base, count) {
    var i = imgs.length;
    imgs[i] = new Array(count);
    for (var j = 0; j < count; ++j) {
        imgs[i][j] = base + j;
    }
}

add_animation("kuva", 5);
add_animation("joku", 8);

Taulukon sisältö tuon ajamisen jälkeen:

js> imgs[0]
kuva0,kuva1,kuva2,kuva3,kuva4
js> imgs[1]
joku0,joku1,joku2,joku3,joku4,joku5,joku6,joku7

punppis kirjoitti:

Yrität käyttää nyt funktioita luokkina.

Se tosiaan olisi aika paha ongelma, JavaScriptissä kun ei ole luokkia. Katso esim. http://en.wikipedia.org/wiki/Javascript­#Prototype-based.

Merri [27.05.2009 06:48:06]

#

Jos jotain luokkien tapaista haluaa vähällä vaivalla, kannattaa kurkata jQuery vs. MooTools ajatuksella läpi. (Saatan suomentaa tuon jossain välissä.)

Paulus M [27.05.2009 09:20:17]

#

Aattelin, että vois vääntää animaattori luokan, koska viimekädessä on monia asioita, mitä animaatioiden kanssa voi tehdä. Niin vois sitten sisällyttää saman luokan toisiinkiin skripteihin, ettei tarttis moneen kertaan koodata.
Sen minkä ymmärsin, niin JS:llä luokka tehdään vain määrittelemällä konsrtuktori metodi?...eikö olekkaan näin?

Millä tavalla noi meikäläisen "luokat" kusee?

Merri [27.05.2009 10:58:43]

#

En ole pahemmin JavaScriptillä luokkia tehnyt, mutta et tallenna tietoja mihinkään sillä tavalla, että ne pysyisivät tallessa. Nyt noista tulee vain toisistaan erillisiä funktiokutsuja.

Tämä on nyt aika pseudohkoa koodia, ei ole aikaa testata, mutta pitäisi mennä lähemmäs tavoitetta:

function Ani() {
    this.animaatiot = new Array();
    this.lkm = 0;
    this.uusi = function(nimi, lkm) {
        for(var i = 0; i < lkm; i++)
        {
            this.animaatiot[this.lkm].push(nimi + String(i));
        }
        this.lkm++;
    }
}

jlaire [27.05.2009 19:10:37]

#

Paulus M kirjoitti:

Aattelin, että vois vääntää animaattori luokan, koska viimekädessä on monia asioita, mitä animaatioiden kanssa voi tehdä. Niin vois sitten sisällyttää saman luokan toisiinkiin skripteihin, ettei tarttis moneen kertaan koodata.

Luokat eivät kuitenkaan ole ainoa tapa tehdä uudelleenkäytettävää koodia.

Paulus M kirjoitti:

Sen minkä ymmärsin, niin JS:llä luokka tehdään vain määrittelemällä konsrtuktori metodi?...eikö olekkaan näin?

Olioita luodaan konstruktorifunktioilla. Jos välttämättä haluat käyttää luokkia, kannattaa käyttää jotain kirjastoa siihen, JavaScript kun ei edelleenkään ole luokkapohjainen.

Metodin voi lisätä kuten Merrin esimerkissä, jos jokainen olio jostain syystä tarvitsee siitä oman kopion Mutta yleensä se ei ole hyvä idea, vaan kannattaa tehdä näin:

function Ani() {
    this.animaatiot = [];
}

Ani.prototype.uusi = function (nimi, lkm) {
    var i = this.animaatiot.length;
    this.animaatiot[i] = [];
    for (var j = 0; j < lkm; ++j) {
        this.animaatiot[i][j] = nimi + j;
    }
}
js> var ani = new Ani()
[object Object]
js> ani.uusi("kuva", 4)
js> ani.uusi("foobar", 7)
js> ani.animaatiot[0]
kuva0,kuva1,kuva2,kuva3
js> ani.animaatiot[1]
foobar0,foobar1,foobar2,foobar3,foobar4,foobar5,foobar6

En nää syytä lukumäärän tallentamiseen erikseen, se vaan lisää mahdollisuuksia virheille.

Paulus M kirjoitti:

Millä tavalla noi meikäläisen "luokat" kusee?

Vaikea vastata, kun en tiedä, mitkä tuossa koodissa ovat näitä "luokkia". Vaikuttaa vähän siltä, ettet ole oikein sisäistänyt JavaScriptin oliosysteemiä.

Paulus M [03.06.2009 10:25:42]

#

sori, tuli vähän taukoa koodauksesta kun piti muuttaa taloa, mutta kiitokset vastauksesta näin myöhässä.

Niin kuin sanoit, niin en olekkaan oikein sisältänyt javan oliosysteemiä, näyttää poikkeavan muista kielistä, kuten Javasta.


Niin mikä merkintä tapa on toi "js>" ja mitä se tarkoittaa?

Metabolix [03.06.2009 10:50:53]

#

Paulus M kirjoitti:

Niin mikä merkintä tapa on toi "js>" ja mitä se tarkoittaa?

Tarkoittanee, että funktio kirjoittaa kyseiset rivit JS-tulkkiinsa, ja seuraavat rivit ovat taas niitä, jotka tulkki tulosti. (JS:ää voi käyttää muutenkin kuin suoraan nettisivuilla.)

Paulus M [04.06.2009 09:53:46]

#

Ok, nyt näyttää aika selkeältä. Kiitokset vielä funktiolle ja Metabolixille.

EDIT:

vielä kysisin, jos jaksatte vastata, että mitä toi prototype sana tarkoittaa?
Etsin netistä ja sain selville, että se viittaa ensimmäiseen objektiin muodostaen jonkun ketjun.

Mutta mitä tapahtuu koneen sisällä tuossa Funktion koodissa, kun ollaan alustamassa
objektia 1 ja 2? Miten prototyyppi toimii? Onko 1:sen ja 2:sen alustamisen kanssa eroja?

Entäs mitä tapahtuisi koneessa, jos ei käyttäisi prototype sanaa?

Metabolix [04.06.2009 11:32:30]

#

Rivi new Olio() luo objektin, kopioi sille kaikki Olio.prototype-objektin ominaisuudet, kutsuu Olio-funktiota niin, että this on tämä uusi objekti, ja lopulta palauttaa vielä kyseisen olion.

Ilman prototypeä taas jäsenet sijoitetaan suoraan Olio-funktion jäseniksi, jolloin niillä ei ole mitään tekemistä yksittäisten Olio-olioiden kanssa.

jlaire [04.06.2009 14:23:49]

#

Käytän Rhinoa JavaScript-komentorivinä. Muitakin vaihtoehtoja luultavasti on, mutta tuo on kelvannut hyvin. Helpottaa huomattavasti kieleen tutusumista ja DOM-riippumattoman koodin testaamista verrattuna johonkin tällaiseen: 1) muokkaa tiedostoa, 2) päivitä sivu selaimessa, 3) tutki selaimen virheilmoituksia, 4) mene kohtaan 1.

JavaScript tosiaan eroaa paljon esim. Javasta. Täällä on joitain hyviä artikkeleita: http://javascript.crockford.com/. Mozillan dokumentaatiosta ja ECMAScript-standardeista löytyy myös paljon tietoa.

Metabolix kirjoitti:

Rivi new Olio() luo objektin, kopioi sille kaikki Olio.prototype-objektin ominaisuudet ...

Jos nyt tarkkoja ollaan, niin itse ominaisuuksia ei kopioida, vaan pelkkä viittaus prototyyppiin. Kun johonkin olion ominaisuuteen viitataan, sitä etsitään ensin itse oliolta ja jos ei löydy, niin sitten olion prototyypiltä, prototyypin prototyypiltä jne..

Standardissa tämä on selitetty näin:

ECMAScript Language Specification 5th Edition Candidate Draft kirjoitti:

ECMAScript supports prototype-based inheritance. Every object created by a constructor has an implicit reference (called the object's prototype) to the value of its constructor's "prototype" property. Furthermore, a prototype may have a non-null implicit reference to its prototype, and so on; this is called the prototype chain. When a reference is made to a property in an object, that reference is to the property of that name in the first object in the prototype chain that contains a property of that name. In other words, first the object mentioned directly is examined for such a property; if that object contains the named property, that is the property to which the reference refers; if that object does not contain the named property, the prototype for that object is examined next; and so on.

Paulus M [04.06.2009 20:23:06]

#

hei hienoa, täytyypä tutustua tuohon Rhinoon niin saa vähän lisää informaatiota virheistä, on vähän hankala tosiaan korjailla, kun etenkään ajonaikaisista virheistä ei tule ilmoituksia....

Paulus M [08.06.2009 16:10:19]

#

Funktio kirjoitti tämään koodin pätkän:

function Ani() {
    this.animaatiot = [];
}

Ani.prototype.uusi = function (nimi, lkm) {
    var i = this.animaatiot.length;
    this.animaatiot[i] = [];
    for (var j = 0; j < lkm; ++j) {
        this.animaatiot[i][j] = nimi + j;
    }
}

kysymys kuuluu: Miten pystyisi tekemään tällä samalla kaavalla Ani:lle funktion, joka antaa jonkun paluuarvon?
Sillä jos pistää tuonne funktion loppuun return 5; niin silloin Ani.prototype.uusi saa arvon 5, vai? Vai millain toimii logiikka?

Grez [08.06.2009 16:15:03]

#

No tuohan tekee Anille funktion. Jos laitat loppuun (ennen kahta viimeistä riviä joissa kummassakin on vain } ) return 5 niin silloin tietenkin Anin funktio uusi(nimi, lkm) palauttaa luvun 5, mutta sitä ennen tekee nuo funktiossa olevat muut toiminnot.

Eli logiikka toimii ihan samalla tavalla kuin aina. (muutenhan se ei olisi loogista)

Paulus M [08.06.2009 16:38:08]

#

mutta millä tavalla pystyn myöhemmin kutsumaan tuota saamaani arvoa, tällä kertaa 5:sta?

Jos haluan myöhemmin käsitellä sitä vistosta niin kutsun esim.
(if ani.prototype.uusi == 5)...plaaplaaplaa...
Eli siis miten saan säilöttyä sen vitosen? Koska eihän se voi olla tuossa ani.prototype.uusi:ssa koska eihän se ole mikään integeri vai onko?

EDIT:
ei vaan sori, menin sekaisin tuosta yhtä suuruun merkistä. Eli sitten kun funktiota kutsutaan, niin voi kirjoittaa vaikka arvo = ani.uusi(plaaplaa);
pahoittelen tyhmyyteni...


Sivun alkuun

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta