Toon posts:

[JS] new Function, by reference voorkomen

Pagina: 1
Acties:

Verwijderd

Topicstarter
Ik heb de volgende testcase, waarvan beide dispatches alert('b') teruggeven, waarvan ik wil dat de eerste netjes alert('a') terug gaat geven. Hoe kan ik zorgen dat de xmlString by value wordt doorgegeven en niet by reference :?

code:
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
<script type="text/javascript">
function EventManager(){
    this.types = new Array();
}
EventManager.prototype.addListener = function(type,action,lifespan){
    if(this.types[type] == null){
        this.types[type] = new EventQueue();
    }
    this.types[type].add(action,lifespan);
}
EventManager.prototype.dispatch = function(type){
    if(this.types[type] != null){
        var eventQueue = this.types[type];
        var events = eventQueue.getEvents();
        
        for(var i=0,j=eventQueue.getLength();i<j;i++){
            events[i].action();
    
            switch(events[i].lifespan){
                // once     : event triggered only once
                // default  : event is always triggered
                case 'once':
                    events[i] = null;
                break;
            }
        }
    }
}
EventManager.prototype.getListeners = function(type){
    if(this.types[type] != null){
        return this.types[type];
    }else{
        return null;    
    }
}
function EventQueue(){
    this.events = new Array();
}
EventQueue.prototype.add = function(action,lifespan){
    this.events.push({action:action,lifespan:lifespan});
}
EventQueue.prototype.getEvents = function(){
    return this.events;
}
EventQueue.prototype.getLength = function(){
    return this.getEvents().length;
}

function foo(){
    var self = this;
    this.eventManager = new EventManager();

    var xmlString = 'alert(\'a\')';
    var func = function(){new Function(xmlString).call(self)};
    this.eventManager.addListener('a',func);
    
    xmlString = 'alert(\'b\')';
    func = function(){new Function(xmlString).call(self)};
    this.eventManager.addListener('b',func);
}
foo.prototype.dispatch = function(){
    this.eventManager.dispatch('a');
    this.eventManager.dispatch('b');
}
var test = new foo();
test.dispatch();
</script>

  • crisp
  • Registratie: Februari 2000
  • Nu online

crisp

Devver

Pixelated

closure vermijden of expliciet scopen?

Intentionally left blank


Verwijderd

Topicstarter
Hmm dat is niet zo mooi dan. Ik wilde het toepassen binnen een lus, maar dan moet je dus diverse losse functies in een array/object gaan stoppen om het te gebruiken. Voor zover ik weet kun je de closure niet vermijden in mijn situatie.


code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
for(var i=0,j=cs.length;i<j;i++){
        var node = cs[i];
        
        switch(node.nodeName.toLowerCase()){
            case "listeners":
                var cschildren = node.childNodes;
                for(var k=0,l=cschildren.length;k<l;k++){
                    var ev = cschildren[k];
                    var func = function(){new Function(getNodeValue(ev)).call(newNode)};
                    newNode.eventManager.addListener(ev.nodeName,func);
                }
            break;
        }
    }

[ Voor 8% gewijzigd door Verwijderd op 19-11-2006 00:27 ]


  • crisp
  • Registratie: Februari 2000
  • Nu online

crisp

Devver

Pixelated

natuurlijk wel:
JavaScript:
1
2
3
4
5
6
7
8
9
10
11
var func = createFunction(getNodeValue(ev), newNode);

// ...

function createFunction(func, obj)
{
    return function()
    {
        new Function(func).call(obj);
    }
}

Intentionally left blank


Verwijderd

Topicstarter
Crisp, maar ga je in de closure niet ook die functie by reference doorgeven, dus eigenlijk min of meer hetzelfde verplaatsen naar de createFunction? :?

  • crisp
  • Registratie: Februari 2000
  • Nu online

crisp

Devver

Pixelated

nee, elke keer dat je createFunction aanroept genereer je een compleet nieuwe scope

Intentionally left blank


Verwijderd

Topicstarter
crisp schreef op zondag 19 november 2006 @ 13:16:
nee, elke keer dat je createFunction aanroept genereer je een compleet nieuwe scope
Hmmz grappig, ik ga het meteen even uitproberen. Enige nadeel kan dan denk ik zijn dat je memory leaks krijgt, maar eerlijk gezegd kan me dat even gestolen worden. Alvast bedankt! :)

edit:

En het werkt! _/-\o_

[ Voor 5% gewijzigd door Verwijderd op 19-11-2006 19:34 ]


  • frickY
  • Registratie: Juli 2001
  • Laatst online: 13:38
Crisp, bedankt!
Stoei ook vaker met dit probleem wanneer ik vanuit een loop een onclick wil zetten met bijvoorbeeld de loop variabele i, welke in een functie moet worden gestopt.
Voorheen deed ik dat door i op te slaan als het id van het item, en in de functie aanroep te verwijzen naar this.id.
In het vervolg weet ik dat ik het zo kan doen;
code:
1
item.onclick = new Function("alert(" + i + ");");

  • crisp
  • Registratie: Februari 2000
  • Nu online

crisp

Devver

Pixelated

frickY schreef op maandag 27 november 2006 @ 14:38:
[...]
In het vervolg weet ik dat ik het zo kan doen;
code:
1
item.onclick = new Function("alert(" + i + ");");
of zo:
JavaScript:
1
2
3
4
5
6
item.onclick = createClickHandler(i);

function createClickHandler(i)
{
    return function() { alert(i); };
}

;)

Intentionally left blank


  • user109731
  • Registratie: Maart 2004
  • Niet online
@crisp: waarom zou je dat laatste gebruiken, om performance redenen? (functie constructor is langzaam?) :)

  • crisp
  • Registratie: Februari 2000
  • Nu online

crisp

Devver

Pixelated

Grote prutser schreef op maandag 27 november 2006 @ 15:03:
@crisp: waarom zou je dat laatste gebruiken, om performance redenen? (functie constructor is langzaam?) :)
jep, afhankelijk van de JS-implementatie is de constructie met de closure 25% tot 800% sneller

Intentionally left blank

Pagina: 1