Check alle échte Black Friday-deals Ook zo moe van nepaanbiedingen? Wij laten alleen échte deals zien

[JS] Prototyping

Pagina: 1
Acties:

  • Mei
  • Registratie: Juni 2005
  • Laatst online: 17-10-2024
JavaScript:
1
2
3
4
5
6
7
8
9
10
11
12
_Collection = function(sSelector) {
    return this.select(sSelector);
}

_Collection.prototype = {
    select: function(sSelector, sContainer, sTagName) {
        return aElements;
    },
    id: function(aElements, sID, bRemove) {
        //Do some stuff
    },
}


Als ik een nieuwe instance van _Collection maak, dan haalt this.select() netjes alle elementen uit de pagina die voldoen aan de CSS selector die via de parameter sSelector doorgegeven is. de returnvalue van aElements is dan een array met objecten. Wil ik vervolgens op die instance de method id() uitvoeren, dan geeft Firefox de melding "instance.id is not a function". Laat ik select() in plaats van aElements een gewone string returnen, dan kan ik id() wél aanroepen.

Ik kan helaas niet zeggen dat ik al van alles geprobeerd heb, want ik heb geen flauw idee in welke richting ik moet zoeken. Bij strings werkt het schijnbaar wel, maar bij een array niet? Hopelijk vind iemand hier het wat minder raar dan ik :P

  • André
  • Registratie: Maart 2002
  • Laatst online: 19-11 11:08

André

Analytics dude

Haal die komma op regel 11 eens weg :?

  • Mei
  • Registratie: Juni 2005
  • Laatst online: 17-10-2024
Nee :+ Firefox valt daar toch niet over en in de volledige code komen er nog een aantal andere methods na id(), dus dan kan die komma daar zonder problemen blijven staan.

  • Clay
  • Registratie: Oktober 1999
  • Laatst online: 14-11 16:23

Clay

cookie erbij?

Je _Collection constructor geeft geen instantie terug, maar het resultaat van die select call en dat is gewoon een array. Id is daar dus geen function van, die zou aan _Collection instanties zitten mits die constructor gewoon niets returnt. De instantie ervan geeft je dan zowel de select() als id() functies ter beschikking. In die collection zelf zou je dan een array bij kunnen houden met nog wat prototyped functions om daar dingen mee te doen;

JavaScript:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function Collection(sSelector) {
    this.elements = this.select(sSelector);
}

Collection.prototype = {
    select: function(sSelector, sContainer, sTagName) {
        // dingen
        return aElements;
    },
    id: function(sID, bRemove) {
        this.elements; // heb je hier dan al
        //Do some stuff
    },
}

var bla = new Collection("div p span");
bla.id( ... );

[ Voor 7% gewijzigd door Clay op 29-02-2008 16:43 ]

Instagram | Flickr | "Let my music become battle cries" - Frédéric Chopin


  • Mei
  • Registratie: Juni 2005
  • Laatst online: 17-10-2024
Hmm, je kan dus niet een custom object type maken dat eigenlijk een array is, maar wel met methods specifiek voor dat objecttype?

  • Clay
  • Registratie: Oktober 1999
  • Laatst online: 14-11 16:23

Clay

cookie erbij?

Kan ook. Maar de array constructor heeft als arguments de elementen van die array he:

JavaScript:
1
2
3
4
5
6
7
8
9
10
11
12
function Collection() {
   this.push.apply(this, arguments);
}

Collection.prototype = new Array();
Collection.prototype.select = function() {
   // dingen
}

var a = new Collection(1,2,3,4);

alert(a[2]); // 3!

Instagram | Flickr | "Let my music become battle cries" - Frédéric Chopin


  • Mei
  • Registratie: Juni 2005
  • Laatst online: 17-10-2024
Ik snap helaas niet wat je daar precies doet. Zou het het misschien stap voor stap willen uitleggen?

//edit: nouja, het gaat eigenlijk alleen om de regel met this.push.apply()

[ Voor 28% gewijzigd door Mei op 29-02-2008 17:14 ]


  • Clay
  • Registratie: Oktober 1999
  • Laatst online: 14-11 16:23

Clay

cookie erbij?

Push is een native functie van Array, en omdat de hele prototype wordt overschreven met een instantie daarvan, hebben Collection instanties die nu ook (en alle andere functions van array).

Apply is de toverstok van javascript waarmee je alles daarheen kan sturen waar jij het heen wil hebben, en in dit geval wordt de arguments array (die daar [1,2,3,4] bevat) losgelaten op die push, in de scope van de Collection instantie. Eigenlijk staat daar dus:

JavaScript:
1
this.push(1, 2, 3, 4);


;)

Instagram | Flickr | "Let my music become battle cries" - Frédéric Chopin


  • Mei
  • Registratie: Juni 2005
  • Laatst online: 17-10-2024
De losse functies snap ik wel, het is alleen de combinatie die ik niet snap. Zou je
JavaScript:
1
this.push.apply(this, arguments);
niet gewoon als
JavaScript:
1
this.push(arguments)
kunnen schrijven? Waarom de apply?

Hmm... Er begint me misschien iets te dagen: is de apply om te zorgen dat de array van arguments als losse variabelen aan this wordt toegevoegd?

Maar blijf het een beetje raar vinden. Als de constructor Collection sowieso al een array output, waarom je dan alsnog de gehele Array prototype moet overnemen om het te laten werken.

//edit: Hmm, vet: "this.push has no properties". Het lijkt me dat
JavaScript:
1
Collection.prototype = new Array();
niet klopt. Ik vond het al een beetje rare regel...

[ Voor 13% gewijzigd door Mei op 29-02-2008 18:03 ]


  • crisp
  • Registratie: Februari 2000
  • Laatst online: 00:58

crisp

Devver

Pixelated

Omdat push de waarden als aparte argumenten wil hebben ;)

Verder werkt Clay's voorbeeld prima hoor :?

[ Voor 20% gewijzigd door crisp op 29-02-2008 20:43 ]

Intentionally left blank


  • Mei
  • Registratie: Juni 2005
  • Laatst online: 17-10-2024
Jaaa, OK? Sorry, maar snap er echt niks meer van nu :P MDC pagina over push() nog eens doorgelezen, maar het wordt me er allemaal niet duidelijker uit waarom hij die code nou zo gemaakt heeft.

  • Mei
  • Registratie: Juni 2005
  • Laatst online: 17-10-2024
JavaScript:
1
2
3
4
5
6
7
8
9
10
11
12
13
_Collection = function(sSelector) {
    this.push.apply(this, this.select(sSelector));
}

_Collection.prototype = new Array();
_Collection.prototype = {
    select: function(sSelector, sContainer, sTagName) {
        return aElements;
    },
    id: function(aElements, sID, bRemove) {
        //Do some stuff
    },
}


Dit heb ik nu. arguments kon ik niet gebruiken, want ik geef geen argumenten door. Dat is het enige punt volgens mij waarop mijn code van Clays voorbeeld afwijkt.

edit:
Shit, dubbelpost...


//Nog een edit: (nee, geen tags, dan krijg je van die irritante kleine lettertjes... :P ) Ik zie nu nog een verschil tussen Clays code en de mijne. Ik geef eerst de Collection prototype de Array prototye en daarna overschrijf ik dat weer vrolijk met een object met methods erin :+ Nu eens kijken of je ook objects kan mergen in JS...

[ Voor 27% gewijzigd door Mei op 29-02-2008 20:54 ]


  • crisp
  • Registratie: Februari 2000
  • Laatst online: 00:58

crisp

Devver

Pixelated

JavaScript:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
Object.extend = function(dest, source, allowOverwrite)
{
    for (var prop in source)
    {
        if (source.hasOwnProperty(prop) && (allowOverwrite || !dest.hasOwnProperty(prop)))
            dest[prop] = source[prop];
    }

    return dest;
}

_Collection.prototype = new Array(); 
Object.extend(_Collection.prototype,
{
    select: function(sSelector, sContainer, sTagName)
    {
        return aElements;
    },
    id: function(aElements, sID, bRemove)
    {
        //Do some stuff
    }
});

;)
Sowieso is de gehele prototype property overschrijven door een object nooit slim, je overschrijft daarmee ook de constructor property.

Intentionally left blank


Verwijderd

crisp schreef op vrijdag 29 februari 2008 @ 21:10:
Sowieso is de gehele prototype property overschrijven door een object nooit slim, je overschrijft daarmee ook de constructor property.
Voor meer info daarover is er dit artikel geschreven door Joost Diepenmaat.

  • Mei
  • Registratie: Juni 2005
  • Laatst online: 17-10-2024
@Blues: leesvoer is altijd goed. Ga ik straks eens even lezen :)
crisp schreef op vrijdag 29 februari 2008 @ 21:10:
JavaScript:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
Object.extend = function(dest, source, allowOverwrite)
{
    for (var prop in source)
    {
        if (source.hasOwnProperty(prop) && (allowOverwrite || !dest.hasOwnProperty(prop)))
            dest[prop] = source[prop];
    }

    return dest;
}

_Collection.prototype = new Array(); 
Object.extend(_Collection.prototype,
{
    select: function(sSelector, sContainer, sTagName)
    {
        return aElements;
    },
    id: function(aElements, sID, bRemove)
    {
        //Do some stuff
    }
});

;)
Sowieso is de gehele prototype property overschrijven door een object nooit slim, je overschrijft daarmee ook de constructor property.
Aah, Crisp gooit zijn extend functie weer in het spel :P Volgens mij heb je me enkele maanden geleden ook iets met die functie uitgelegd. Ben het helemaal vergeten :o Ga gelijk dat topic weer even opzoeken, daar stond ook de hele uitleg van die functie in. Bedankt voor het duwtje in de goede richting!

Hebben jullie verder misschien nog wat aan te merken op hoe ik de boel aanpak? Ik ben nu bezig met een JS library, voornamelijk om ervan te leren. Heb al veel naar jQuery gekeken, veel zelf weten te bedenken. Ook een deel gemaakt met ervaring die ik met het devven voor Drupal heb opgedaan. Sinds vandaag ook wat naar de Prototype library aan het kijken. Al met al heel interessant om alles te zien en leuk om van te leren.

  • Mei
  • Registratie: Juni 2005
  • Laatst online: 17-10-2024
Woei, het oude topic gevonden en de reply gelezen waarin jij alles had uitgelegd. Ik ben nu zover:
JavaScript:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/**
Object prototyping
*/
Object.prototype = {
    /**
    Extend an object (kind of object merging)
    Thanks to Tino Zijdel for his example
    
    @param oSource object The object to copy the properties from
    @param bAllowOverwrite boolean Whether to override existing properties or not
    */
    extend: function(oSource, bAllowOverwrite) {
        for (var property in oSource) {
            if(oSource.hasOwnProperty(property) && (bAllowOverwrite || !this.hasOwnProperty(property))) {
                this[property] = oSource[property];
            }
        }
        
        return this;
    }
}


Een iets aangepaste versie van jouw extend method dus. Ik laat zowel de properties naar this kopiëren als dat ik this return. Dat eerste zorgt ervoor dat oObject.extend(oSourceObject) gewoon oObject aanpast en dat laatste zorgt ervoor dat dingen gechaind kunnen worden: oObject.extend(oSourceObject).anotherMethod().

  • crisp
  • Registratie: Februari 2000
  • Laatst online: 00:58

crisp

Devver

Pixelated

aj, Object prototypen is wel erg drastisch en wordt door velen als 'verboten' (zoekterm ;)) beschouwd...

Intentionally left blank


  • Mei
  • Registratie: Juni 2005
  • Laatst online: 17-10-2024
Oooh, wacht, er gaat me iets dagen :P Het werkte niet in IE. Da's waar ook.

  • crisp
  • Registratie: Februari 2000
  • Laatst online: 00:58

crisp

Devver

Pixelated

Mei schreef op zaterdag 01 maart 2008 @ 13:37:
Oooh, wacht, er gaat me iets dagen :P Het werkte niet in IE. Da's waar ook.
nee :?
Ik doelde op Object.prototype is verboten. En het is niet alleen vanwege hashmaps, elk ander primitive object overerft van Object. Heb je extend() nodig voor Array of voor String of voor Number of voor Date? Als het antwoord op die vraag 'nee' is dan is Object prototypen pure overkill ;)

Intentionally left blank

Pagina: 1