[JavaScript] Vraag omtrent private functions

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • SideShow
  • Registratie: Maart 2004
  • Laatst online: 21-09 15:49

SideShow

Administrator

Topicstarter
Hallo

Ik zit wat kennis te verzamelen omtrent JavaScript design patterns en ben het "Revealing Prototype Pattern" aan het toepassen.

Ik zal mijn vraag starten met volgende voorbeeld:


JavaScript:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//Constructor
function Dog(age) {
    this.age = age,
    this.humanAge = Dog.prototype.getHumanAge.call(this);
};

Dog.prototype = function() {
    var factor = 7,
        getHumanAge= function() {
            return factor * this.age;
        };
    
    //Expose private members
    return { getHumanAge: getHumanAge};
}();

var tommy = new Dog(4);
console.log(tommy.humanAge);
console.log(tommy.getHumanAge());


Hier zie je dus een prototype met een gemeenschappelijke private member, namelijk "factor".
Het probleem is, dat ik dus de functie getRealAge wil prototypen om efficiënter geheugenbeheer te hebben, en ik wil de functie aanspreken in de constructor van Dog, MAAR wil tegelijkertijd dat ze niet publiek wordt. Maar net omdat je het wil gebruiken in de constructor, moet je ze wel publiek maken.

Verkracht ik hier javascript, of kan iemand me de weg wijzen?

Ik wil dit toepassen in mijn webapplicatie, waar een javascript object een soort client side control voorstelt. Het object is dus ook gelinkt aan een bestaand DOM element, waar het zijn output doet. Ik wil dat linken laten gebeuren via een prototype functie in de constructor, maar wil wel dat die functie niet naar buiten komt.

Hopelijk is dit een beetje duidelijk, want tot voor kort (voordat ik de cursus JS Design Patterns had gevolgd) was dit voor mezelf ook chinees :+

Acties:
  • 0 Henk 'm!

  • glashio
  • Registratie: Oktober 2001
  • Laatst online: 24-09 11:05

glashio

C64 > AMIGA > PC

Javascript verkeerd toepassen? Nee waarom... je legt een scope vast in je constructor van elk gecreeerd object. Vind het wel mooi :) Kwa geheugen issues blijft het DOM Element bestaan in geheugen zodra hij dus in je ge-prototyped voorkomt en de daaruit bestaande objecten. Niks mis mee.

> Google Certified Searcher
> Make users so committed to Google that it would be painful to leave
> C64 Gospel
> [SjoQ] = SjoQing


Acties:
  • 0 Henk 'm!

  • SideShow
  • Registratie: Maart 2004
  • Laatst online: 21-09 15:49

SideShow

Administrator

Topicstarter
Mja, ik zoek een manier om het Dog object te initialiseren in de constructor, aan de hand van prototype methods, zonder dat deze publiek worden. (In dit voorbeeld is getHumanAge publiek ... dat wil ik eigenlijk niet)

Acties:
  • 0 Henk 'm!

  • CurlyMo
  • Registratie: Februari 2011
  • Laatst online: 23:11
Ik gebruik deze constructie al een aantal jaar. Javascript class als DOM Element waardoor je de meest waanzinnige nieuwe DOM Elementen kan emuleren.

Een constructie waarin methode private of protected zijn bestaat niet in javascript. Het enige wat je kan doen is in de variabele naam laten weten wat je er als programmeur mee zou moeten. Al mijn private variabelen beginnen met een underscore. Het manipuleren van de waarden van deze variabelen zou dus alleen via functies van de betreffende class moeten gaan. Wanneer je direct een waarde met een underscore aanspreekt, weet je dus dat je de structuur van de class aan het ondermijnen bent.

Hetzelfde geldt overigens voor mijn functies. Functies die alleen intern in mijn framework zouden moeten worden gebruikt hebben een underscore aan het begin. Deze functies zou je dus niet direct moeten aanspreken wanneer je van het framework gebruik maakt.

Sinds de 2 dagen regel reageer ik hier niet meer


Acties:
  • 0 Henk 'm!

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


Acties:
  • 0 Henk 'm!

  • glashio
  • Registratie: Oktober 2001
  • Laatst online: 24-09 11:05

glashio

C64 > AMIGA > PC

SideShow schreef op maandag 30 april 2012 @ 23:32:
Mja, ik zoek een manier om het Dog object te initialiseren in de constructor, aan de hand van prototype methods, zonder dat deze publiek worden. (In dit voorbeeld is getHumanAge publiek ... dat wil ik eigenlijk niet)
Google heeft hier eens mooi voorbeeld over gegeven.

> Google Certified Searcher
> Make users so committed to Google that it would be painful to leave
> C64 Gospel
> [SjoQ] = SjoQing


Acties:
  • 0 Henk 'm!

Verwijderd

SideShow schreef op maandag 30 april 2012 @ 23:15:
Het probleem is, dat ik dus de functie getRealAge wil prototypen om efficiënter geheugenbeheer te hebben
Dit is je probleem: je offert leesbaarheid en beheersbaarheid op voor een verwaarloosbare performance boost. Dit soort optimalisaties ga je pas merken bij tienduizenden instances.

JavaScript:
1
2
3
4
5
6
7
function Dog(age) { 
    var factor = 7;
    this.age = age, 
    this.humanAge = function() { 
        return factor * this.age; 
    }
}; 
CurlyMo schreef op maandag 30 april 2012 @ 23:39:
Een constructie waarin methode private of protected zijn bestaat niet in javascript.
Dat hangt af van je definitie van private. Als Crockford zegt dat het private is, dan kan ik me daar wel in vinden.

Acties:
  • 0 Henk 'm!

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 03:42
SideShow schreef op maandag 30 april 2012 @ 23:15:
Het probleem is, dat ik dus de functie getRealAge wil prototypen om efficiënter geheugenbeheer te hebben, en ik wil de functie aanspreken in de constructor van Dog, MAAR wil tegelijkertijd dat ze niet publiek wordt. Maar net omdat je het wil gebruiken in de constructor, moet je ze wel publiek maken.
Ik geloof niet dat ik precies begrijp wat je wil, aangezien ik hier helemaal geen getRealAge() functie zie. Maar als je bedoelt dat je getHumanAge() private wil houden zonder de factor variable publiek te maken, dan kun je ze toch allebei binnen de closure halen waarmee je factor verbergt:
JavaScript:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
(function() {
    var factor = 7

    var getHumanAge = function() {
        return factor * this.age
    }

    Dog = function(age) {
        this.age = age
        this.humanAge = getHumanAge.call(this)
    }

    Dog.prototype = {
        // public members here
    }
})()

Overigens ben ik het ook met CurlyMo eens: échte private members in scripttalen zijn overrated.

Acties:
  • 0 Henk 'm!

  • CurlyMo
  • Registratie: Februari 2011
  • Laatst online: 23:11
Verwijderd schreef op dinsdag 01 mei 2012 @ 13:30:
Dat hangt af van je definitie van private. Als Crockford zegt dat het private is, dan kan ik me daar wel in vinden.
Het probleem van zijn methode is dat je het hele prototyping principe van Javascript onmogelijk maakt. Zoals hij zelf ook al stelt is het niet mogelijk om in submethodes (via prototyping aangemaakt) je 'private' variabelen aan te spreken. Dat maakt het dus onmogelijk om succesvol je functies te 'extenden' aangezien deze variabelen niet meegenomen worden.
Soultaker schreef op dinsdag 01 mei 2012 @ 14:32:

...dan kun je ze toch allebei binnen de closure halen waarmee je factor verbergt:
Hetzelfde geldt voor deze oplossing.

Je zult door beide oplossingen nooit effectief OO kunnen programmeren met Javascript. Dus gewoon je private wens loslaten en met bijv. variabel namen gaan werken.

Sinds de 2 dagen regel reageer ik hier niet meer


Acties:
  • 0 Henk 'm!

Verwijderd

CurlyMo schreef op dinsdag 01 mei 2012 @ 18:37:
Je zult door beide oplossingen nooit effectief OO kunnen programmeren met Javascript. Dus gewoon je private wens loslaten en met bijv. variabel namen gaan werken.
Als je dat niet erg vindt, bepaal ik dat liever zelf. Inheritance is slechts 1 van de vele aspecten van OOP. Encapsulation is wat mij betreft minstens net zo belangrijk en -- in mijn ervaring -- nuttiger bij het schrijven van goed leesbare code.

Acties:
  • 0 Henk 'm!

  • CurlyMo
  • Registratie: Februari 2011
  • Laatst online: 23:11
Verwijderd schreef op dinsdag 01 mei 2012 @ 22:18:
[...]


Als je dat niet erg vindt, bepaal ik dat liever zelf. Inheritance is slechts 1 van de vele aspecten van OOP. Encapsulation is wat mij betreft minstens net zo belangrijk en -- in mijn ervaring -- nuttiger bij het schrijven van goed leesbare code.
Why so serious :) Iedereen is vrij te doen wat hij wilt. Ik reageer hier direct op de vraag van de TS waarin het specifiek gaat over prototyping en private members. Ik geef dus gewoon de pro's en cons van een bepaalde keuze aan.

Sinds de 2 dagen regel reageer ik hier niet meer


Acties:
  • 0 Henk 'm!

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 03:42
CurlyMo schreef op dinsdag 01 mei 2012 @ 18:37:
Het probleem van zijn methode is dat je het hele prototyping principe van Javascript onmogelijk maakt. Zoals hij zelf ook al stelt is het niet mogelijk om in submethodes (via prototyping aangemaakt) je 'private' variabelen aan te spreken. Dat maakt het dus onmogelijk om succesvol je functies te 'extenden' aangezien deze variabelen niet meegenomen worden.
Eh, dat is nonsens?

Private attributed/methoden kun je per definitie niet overerven. Dus is het ook geen probleem dat dat niet kan. Dat geldt in Java of C++ net zo goed als in JavaScript.

De enige "beperking" van die closure-aanpak is dat je alle private methoden tegelijk moet definiëren (je kunt ze dus niet later nog aan het prototype toevoegen) maar ook dat is in andere OO-gebaseerde talen niet anders.

[ Voor 15% gewijzigd door Soultaker op 01-03-2013 18:27 ]


Acties:
  • 0 Henk 'm!

  • CurlyMo
  • Registratie: Februari 2011
  • Laatst online: 23:11
Soultaker schreef op dinsdag 01 mei 2012 @ 23:32:
[...]

Eh, dat is nonsens?

Private attributed/methoden kun je per definitie niet overerven. Dus is het ook geen probleem dat dat niet kan. Dat geldt in Java of C++ net zo goed als in JavaScript.
Dat snap ik maar neem het volgende voorbeeld:

JavaScript:
1
2
3
4
5
6
7
8
9
test=function()
{
var a = 1;
var b = 2;
function print()
{
return a;
}
}

Dit object is dus niet over te erven zodat je de functie print kan gaan gebruiken in een nieuwe object.
JavaScript:
1
2
3
4
5
6
7
8
9
10
test=function()
{
this.a = 1;
this.b = 2;
}

test.prototype.print=function()
{
return this.a;
}

Het is me duidelijk dat je na overerving niet direct een private member zou moeten kunnen benaderen. In het tweede voorbeeld heb je wel de mogelijkheid om de functie print over te erven in het eerste voorbeeld niet. Dat is wat ik bedoel.

JavaScript:
1
2
3
4
5
test1=function()
{
this.a=3;
this.b=4;
}

Stel nou je wilt object 'test1' object 'test' laten overerven dan kan je de al bestaande functie print gaan gebruiken voor nieuwe variabelen in object 'test1'.

Sinds de 2 dagen regel reageer ik hier niet meer

Pagina: 1