Toon posts:

[js] object probleem

Pagina: 1
Acties:

Verwijderd

Topicstarter
Ben bezig met een object gestructureerde opbouw van een pagina. Er is een moederobject met wat properties en ook een _layer object erin die gekoppeld wordt met de paginastructuur:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
function TDynNode() {
    //wat properties
    
    var layer = document.createElement('div');
    layer.className = 'neptuneDynNode';
    
    var handles = document.createElement('div');
    handles.className = 'neptuneDynNodeHandles';
    handles.style.display = 'block';
    handles.innerHTML = 'layoutverneukende html (divjes)';
    layer.appendChild(handles);
    
    var content = document.createElement('div');
    content.innerHTML = this.name;
    layer.appendChild(content);
    this._layer = layer;
    this._handles = handles;
    this._content = content;
    this.repaint();
}

dat repaint method is met prototyping toegevoegd en regelt het doorgeven van object properties naar de _layer style properties.

als ik objecten aan elkaar hang worden ook de layers in het DOM aan elkaar gehangen (onderaan in de functie):
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
TNode.prototype.appendChild = function(obj) {
    if (!this._firstChild) {
        obj._parentNode = this;
        this._firstChild = obj;
        this._lastChild = obj;
        this._childNodes[this._childNodes.length] = obj;
    } else {
        obj._parentNode = this;
        obj._previousSibling = this._lastChild;
        this._lastChild._nextSibling = obj;
        this._lastChild = obj;
        this._childNodes[this._childNodes.length] = obj;
    }
    if (obj._layer) {
        var parentLayer = (this._layer)? this._layer: document.body;
        document.body.appendChild(obj._layer);
        obj.repaint();
    }
    return(obj)
}

dit werkt allemaal. Als ik een paar objecten aanmaak komen ze keurig achter elkaar in de body te zitten.

Alleen als ik van dit object een descendant maak, werkt het niet meer:
PHP:
1
2
3
4
5
function TPanel() {
    this._type = 'panel';
}

TPanel.prototype = new TDynNode();

het object komt wel netjes in de hele objectstructuur, alleen het _layer object wordt overschreven door de navolgende _layerobjecten. Dit heb ik dus niet als ik het TDynNode object gebruik, wel als ik het TPanel object gebruik, terwijl die in niks verschilt van het moederobject (op die _type na, maar die kan je ook nog weghalen)

vraag is dus hoe dat in 's hemelsnaam kan

[ Voor 16% gewijzigd door Verwijderd op 21-04-2003 19:19 ]


Verwijderd

Topicstarter
subtiele kick: heb nu een halve dag vanalles uit ziten proberen maar zonder resultaat.

even een voorbeeldje online gezet: http://www.rikkertkoppes.com/neptune/objtest2.htm
onload geeft ie nog even de object boom eruit, zoals je kan zien is de structuur er wel, alleen de eerste _layers wordt overschreven door de tweede. Dit gebeurt dus niet als ik twee TDynNode objecten aanmaak, of twee verschillende objecten (TDynNode en TPanel)

de js library is deze: belangrijkste functies staan een beetje in het midden (gewoon diegene die ik hierboven heb aangegeven)
http://www.rikkertkoppes.com/neptune/libraries/standard.js

Verwijderd

Ik snap je probleem nog niet helemaal. Geef 's een stukje code met daarbij aangegeven wat er gebeurd en wat er zou moeten gebeuren.

  • Clay
  • Registratie: Oktober 1999
  • Laatst online: 22-06 13:51

Clay

cookie erbij?

In dit stukje zit iets wat niet de bedoeling kan zijn:
JavaScript:
1
2
3
4
5
function TPanel() { 
    this._type = 'panel'; 
} 

TPanel.prototype = new TDynNode();


De laatste regel, ...prototype = new ... maak je voor de prototype van je TPanel een instantie aan van TDynNode. dat kan ook wel (en moet ook), maar de elementen die deze aanroep genereert wil je daar nog niet hebben, die wil je pas bij instanties van TPanel zelf hebben.

Het makkelijkste is om te checken of de aanroep argumenten meegeeft. Als die er niet zijn return je gewoon, maar heb je wel een geldige instantie voor de prototype, maar dan moet de functie wel argumenten hebben om op te checken. Je kan ook checken om de arguments.caller (dacht ik)
Om de descendant compleet te maken moet je in de constructor een apply gebruiken:

JavaScript:
1
2
3
4
function TPanel() {
   TDynNode.apply(this, arguments);
   ...
}


Zodat je dus bij een instatie van TPanel html wel op het juiste moment en alleen voor de instaties ervan de super aanroept en htmlelements maakt voor TPanel. Met een paar checks en het gebruik van object.appy kan je dus werkende overerving maken.

Apply werkt overigens niet op 5.0, maar daar zijn hacks voor, oa deze:
JavaScript:
1
2
3
4
5
6
7
8
if(!Function.apply) 
Function.prototype.apply = function(obj, args) {
    var sArg = [], l = args.length;
    for(var i=0; i<l; i++) { sArg[i] = 'arg['+i+']'; }
    var action = new Function('obj','f','arg',
        'obj.$apply = f; obj.$apply(' + sArg.join(',') + ')');
    return action(obj, this, args);
}

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


Verwijderd

Topicstarter
woei clay, da's effe een harde noot :D

als ik het goed begrijp is het probleem het volgende: in TDynNode wordt bij de aanmaak ervan een _layer gemaakt. Je krijgt dus mooi twee _layers als je 2 instanties van TDynNode maakt.
Wat er fout gaat bij TPanel is dat er in die TPanel z'n prototype al een _layer is aangemaakt omdat dat een instantie is van TDynNode. Als ik dus twee instanties aanmaak van TPanel zit daar de _layer in die bij de overerving erin is gekwakt. 2x dezelfde dus

En over die apply: als ik het goed begrijp zorgt die ervoor dat het TDynNode object wordt "uitgevoerd" binnen TPanel. Da's dus een ander soort manier van overerving? Dan hoef ik niet meer het prototype te overschrijven? en komen de methods dan wel mee?

dus, aangezien er geen argumenten worden meegegeven:

PHP:
1
2
3
4
5
6
7
8
9
function TPanel() {
  TDynNode.apply(this)
  //rest van de properties
}

// alle vervangende en nieuwe methods

TPanel.prototype.method = function() {
}



edit:

of wat ik me nu bedenk:
als ik in TDynNode een method maakt die de hele layer bende aanmaak en die in TPanel (en al z'n broertjes en zusjes) pas aanroep zou het ook moeten werken denk ik:

PHP:
1
2
3
4
5
6
7
8
9
10
TDynNode.prototype.createStuff = function() {
  //creeer layers en voeg ze aan het document toe
}

function TPanel() {
  //properties
  this.createStuff()
}

TPanel.prototype = new TDynNode();

dan krijg je natuurlijk wel weer problemen als je descendants van TPanel zou willen maken. Nu is TDynNode eigenlijk een abstract object waar alleen descendants van worden getrokken, dus dit lijkt me ook te kunnen, maar met die apply is generieker lijkt me.

Vanmiddag effe stoeien :D

[ Voor 49% gewijzigd door Verwijderd op 23-04-2003 11:36 ]


  • Clay
  • Registratie: Oktober 1999
  • Laatst online: 22-06 13:51

Clay

cookie erbij?

De prototype = new superObject() moet wel blijven staan, die linkt de functies van de super ook aan de sub, de apply zorgt er idd voor dat wat er in de constructor van de super staat aangeroepen wordt in de context van de sub (alsof het een object functie was van de sub). Met die 2 constructies kan je dus volledige overerving regelen. Het enige waar je idd voor moet zorgen is dat er in die prototype constructie geen layers aangemaakt moeten worden, zodat je geen visuele instantie te zien krijgt.
En dat kan dus het makkelijkst door op afwezigheid argumenten te checken. Die geeft je niet mee bij het prototypen, en bijvoorbeeld wel bij instanties. maar als je die ook niet meegeeft voor instanties moet je wat anders verzinnen.
En zo kan je dus ook makkelijk subs van subs etc. maken. :)

[ Voor 3% gewijzigd door Clay op 23-04-2003 12:02 ]

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


Verwijderd

Hmm, de werking onder motorkap van die objecten snap ik nog niet helemaal. Neem de volgende code:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
function TDynNode() { 
  this.name='TDynNode';
} 
 
function TPanel() { 
  TDynNode.apply(this,arguments);
  this.name='TPanel';
} 
TPanel.prototype = new TDynNode();

var o=new TPanel();
alert(o.constructor==TPanel); //false
alert(o.constructor==TDynNode); //true

Waarom is de constructor van het o-object TDynNode. Da's toch niet logisch :? Hoe moet javascript dan de prototype-chain doorlopen?

Kijk naar het volgende:
PHP:
1
2
3
o.__proto__.constructor==TDynNode
o.__proto__.__proto__.constructor==TDynNode
o.__proto__.__proto__.__proto__.constructor==Object

Ik begin het aardig niet meer te snappen 8)7

  • oh,when?
  • Registratie: April 2000
  • Niet online

oh,when?

...

Nu we het toch over inheritance hebben ( even los van bovenstaand probleem ), kun je in Javascript niet gebruik maken van een manier ala Java extends?

Doekman:

Dat komt omdat in Javascript de constructor property altijd leest van het object constructor prototype property ( dus Foo.__proto__.constructor ). Zie ECMA-626. In Flash MX en Flash 5 wordt de constructor property direct gekoppeld aan het Object zelf (zoals je dat verwacht volgens bovenstaand voorbeeld ). Het verschil tussen ECMA-626/Javascript en Actionscript hierin heeft al menigeen tegen rare problemen aangelopen die een thread op zichzelf waard zijn.

:)

"You're only as good, as what you did last week."


  • Clay
  • Registratie: Oktober 1999
  • Laatst online: 22-06 13:51

Clay

cookie erbij?

Iets ala dit zou volgens mij moeten kunnen:
JavaScript:
1
2
3
4
5
6
7
8
9
10
//fictief, nu

function Person(name) {
   this.name= name
}

function Man(name).extends(Person) {
   // Prototype automagisch gekoppeld
   // Person constructor automagisch in deze scope geroepen
}  // <-- of die .extends moet hier


waarbij je dan Function.extends = function(super) moet bouwen. daarbinnen is this de sub van de super die je meegeeft aan de extends. dus this.prototype = new super() zou dan al moeten werken, en dan hoef je alleen de apply in zien te bouwen om de constructor van de super in de scope van de sub aan te roepen... (is't nog te volgen :D)

* Clay gaat even spelen

[ Voor 5% gewijzigd door Clay op 26-04-2003 14:39 ]

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


  • oh,when?
  • Registratie: April 2000
  • Niet online

oh,when?

...

extends is volgens mij een reserved keyword....dan moet je extend gebruiken:

JavaScript:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
Function.prototype.extend = function(superClass) {
   this.prototype.__proto__ = superClass.prototype;
};

Shape = function(name) {
   this.name = name;
};

Circle = function(name, radius) {
   super(name);
   this.radius = radius;
};

Circle.extend(Shape);


zou dan moeten voldoen.....

:)

"You're only as good, as what you did last week."


  • Clay
  • Registratie: Oktober 1999
  • Laatst online: 22-06 13:51

Clay

cookie erbij?

Yup, dat heb ik nu ook ongeveer werkend :) maar nu nog die "apply" werkend zien te krijgen

edit:
woei


JavaScript:
1
// te vroeg gejuichd, bug


Dit lijkt te werken! :D alleen wil ik nu van dat lelijke Man = ... af, dat moet zonder kunnen.

edit:
woei 2


JavaScript:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
Function.prototype.extend = function(Super) {
    var self = this;        
    var func = function() {
        Super.apply(this, arguments);
        self.apply(this, arguments);        
    }

    func.prototype = new Super();
    return func;
}

// Super
function Person(name) {
    this.name = name;
}
    Person.prototype.hail = function() {
        alert('hey!, I\'m ' + this.name );
    }

// Sub
function Man(name, fiets) {
    this.hail();    

    // dit werkte net niet
    alert(fiets)
}

Man = Man.extend(Person)

// Use
new Man('henk', 'bmx');

[ Voor 111% gewijzigd door Clay op 26-04-2003 15:25 ]

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


Verwijderd

Topicstarter
nu zie ik hier af en toe het __proto__ property langskomen. Is dat nou hetzelfde als het prototype? volgens mij ben ik het wel eens tegengekomen in wat as topics en ik dacht eigenlijk dat het gewoon de as variant van prototype was. :?

Verwijderd

het klopt toch dat __proto__ in IE js niet bestaat? ik krijg geen enkel voorbeeld aan het werk waar de __proto__ property gevuld is in IE.

Verwijderd

sorry doekman zit ik nu op jouw account te posten?

  • oh,when?
  • Registratie: April 2000
  • Niet online

oh,when?

...

__proto__ is eigenlijk een een netscape extensie van Javascript en het komt ook niet voor in de ECMA specificaties, maar aangezien ik me eigenlijk alleen bezig hou met AS boeien browser implementaties me niet zo :P Maar toegegeven, het mag eigenlijk niet, en de manier waarop inheritance eigenlijk zou moeten is Clay zijn manier:

JavaScript:
1
SubClass.prototype = new SuperClass();


klein vraagje aan Clay, deze regel:

JavaScript:
1
return func;


wat doe je daar dan mee? Volgens mij hoeft dat eigenlijk helemaal niet :)

"You're only as good, as what you did last week."


Verwijderd

Topicstarter
JavaScript:
1
Man = Man.extend(Person)


wel hoor ;) je wilt toch iets terug krijgen? Alleen is dit dus wel iets wat er een beetje raar uitziet zoals clay al aangaf. Eens kijken of het mooier kan.

[ Voor 38% gewijzigd door Verwijderd op 26-04-2003 17:23 ]


  • Clay
  • Registratie: Oktober 1999
  • Laatst online: 22-06 13:51

Clay

cookie erbij?

JavaScript:
1
2
3
4
5
6
7
8
9
10
Function.prototype.extend = function(Super) {
    var self = this;        
    var func = function() {
        Super.apply(this, arguments);
        self.apply(this, arguments);        
    }

    func.prototype = new Super();
    return func;
}


zonder return func; werkt het idd niet. Die extend moet 2 dingen doen. Het aanroepen ervan moet de prototype van de functie overschrijven met een instantie van de super, dat is dat bla = new Super() stuk. Dat zou idd zonder een return kunnen.

Maar die extend moet er ook voor zorgen dat de super wordt aangeroepen met de argumenten die die zelf krijgt als je een instantie van het object maakt. En daarvoor zit die functie daar. Eigenlijk gooit deze constructie de bestaande functie weg, en geeft een nieuwe terug, die zowel de oude, als de super in de scope van zichzelf aanroept ;) waarbij ook de prototype van de oude behouden blijft (hoewel ik nu ik nog een keer kijk zelf niet snap hoe dat kan) vandaar ook die dubbele apply. En om dat bij het maken van een instantie voor elkaar te krijgen moet die wat returnen, want je kan niet this = watAnders; doen.

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

Pagina: 1