Javascript closure

Pagina: 1
Acties:

Onderwerpen


  • ZeroXT
  • Registratie: December 2007
  • Laatst online: 24-09 17:12
Beste tweakers,

Ik heb een probleem met het aanroepen van een variable binnen een closure. Krijg elke keer de melding dat this.var niet bestaat.

Nu heb ik een simpel voorbeeld code hieronder geplaats:


JavaScript:
1
2
3
4
5
6
7
8
9
function functie1()
{
    this.var = 'test';

    this.functie = function()
    {
        this.object.addEventListener('click', function() { alert(this.var); }, false)
    }
}


Ik heb in Google gezocht naar javascript closures maar tevergeefs. Heeft iemand een helder moment voor mij? :)

  • 418O2
  • Registratie: November 2001
  • Laatst online: 11:31
Uhm, het is toch logisch dat this een andere scope heeft in die functie?

Als je hem zou willen gebruiken zou je hem al mee moeten geven op 1 of andere manier.

  • ZeroXT
  • Registratie: December 2007
  • Laatst online: 24-09 17:12
Ik heb geprobeerd deze mee te geven:

JavaScript:
1
2
3
4
5
6
7
8
9
function functie1()
{
    this.var = 'test';

    this.functie = function()
    {
        this.object.addEventListener('click', ( function(this) { alert(this.var); } )(this);, false)
    }
}


Maar ook dit lukt niet.

  • CoolGamer
  • Registratie: Mei 2005
  • Laatst online: 24-09 20:50

CoolGamer

What is it? Dragons?

Je zou het op deze manier kunnen doen.
JavaScript:
1
2
3
4
5
6
7
8
9
function functie1()
{
    var v = 'test';

    this.functie = function()
    {
        this.object.addEventListener('click', function() { alert(v); }, false)
    }
}

¸.·´¯`·.¸.·´¯`·.¸><(((º>¸.·´¯`·.¸><(((º>¸.·´¯`·.¸.·´¯`·.¸.·´¯`·.¸<º)))><¸.·´¯`·.¸.·´¯`·.¸.·´¯`·.¸


  • ZeroXT
  • Registratie: December 2007
  • Laatst online: 24-09 17:12
Bedankt voor het antwoord maar dat is in mijn geval niet mogelijk omdat ik eigenlijk een functie wil mee sturen. En die functie die moet met this aangesproken worden want hij word op meerdere plekken aangeroepen.

JavaScript:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function functie1()
{
    this.var = 'test';    

    this.functie = function()
    {
        this.object.addEventListener('click', function() { this.volgende; }, false)
    }
    
    this.volgende = function()
    {
        alert(this.var);
    }
}

var test = new functie1();
    test.volgende();

  • CoolGamer
  • Registratie: Mei 2005
  • Laatst online: 24-09 20:50

CoolGamer

What is it? Dragons?

Dan zo je het op deze manier kunnen doen:
JavaScript:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function functie1()
{
    var self = this;
    this.v = 'test';    

    this.functie = function()
    {
        this.object.addEventListener('click', function() { self.volgende(); }, false)
    }
    
    this.volgende = function()
    {
        alert(self.v);
    }
}

var test = new functie1();
    test.volgende();

¸.·´¯`·.¸.·´¯`·.¸><(((º>¸.·´¯`·.¸><(((º>¸.·´¯`·.¸.·´¯`·.¸.·´¯`·.¸<º)))><¸.·´¯`·.¸.·´¯`·.¸.·´¯`·.¸


  • Feanathiel
  • Registratie: Juni 2007
  • Niet online

Feanathiel

Cup<Coffee>

Verkeerd gelezen

[ Voor 142% gewijzigd door Feanathiel op 18-11-2010 11:52 ]


  • X-Lars
  • Registratie: Januari 2004
  • Niet online

X-Lars

Just GoT it.

Volgens mij werkt dat ook nog niet (self.volgende wordt niet uitgevoerd). Dit werkt:
HTML:
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
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <title>Closure</title>
        <script type="text/javascript">
            function functie1() 
            { 
                this.var = 'test';
            
                this.object = document.getElementById('foo');
            
                var oOtherScope = this;

                this.functie = function() 
                { 
                    this.object.addEventListener('click', function() { oOtherScope.volgende(); }, false) 
                } 

                this.volgende = function() 
                { 
                    alert(oOtherScope.var);
                } 
            }
        </script>
    </head>
    <body onload="var test = new functie1(); test.functie(); test.volgende();">
        <button id="foo">button</button>
    </body>
</html>


Edit:
JavaScript:
1
this.object.addEventListener('click', oOtherScope.volgende, false) 

[ Voor 5% gewijzigd door X-Lars op 18-11-2010 11:45 . Reden: Variatie (kan je alleen geen argumenten meesturen) ]


  • ZeroXT
  • Registratie: December 2007
  • Laatst online: 24-09 17:12
TheCoolGamer.. ik dank je hartelijk. Opgelost en wel

Edit:
Bedankt voor je antwoord X-Lars alleen het was al opgelost :)

[ Voor 40% gewijzigd door ZeroXT op 18-11-2010 12:10 ]


  • X-Lars
  • Registratie: Januari 2004
  • Niet online

X-Lars

Just GoT it.

Fine, maar die click handler werkt niet lijkt me.

Anyway, begrijp je nu ook waarom je eigen brouwsels niet werkten? En dan met name dat gegoochel met 'this' en self-invoking functions.

Acties:
  • 0 Henk 'm!

  • ZeroXT
  • Registratie: December 2007
  • Laatst online: 24-09 17:12
Yes en ik had al eerder met self-invoking functies gewerkt, was alleen weer een tijdje vergeten dus moest het weer even ophalen.

Acties:
  • 0 Henk 'm!

  • trinite_t
  • Registratie: Maart 2003
  • Laatst online: 22-09 13:25
Als je dit toch echt netjes wilt oplossen (zonder var x = this in object scope), the gebruiken kun je toch ook met apply werken? Of zie ik dat nu verkeerd?

The easiest way to solve a problem is just to solve it.


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 22-09 16:37

.oisyn

Moderator Devschuur®

Demotivational Speaker

Hoe dan? Je zult ook met apply gewoon de 'this' mee moeten geven. Dat kan alleen door die in een variabele op te slaan, want de 'this' binnen de context waarin je de apply doet is niet de juiste. Constructies als bind() werken ook op die manier.

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • X-Lars
  • Registratie: Januari 2004
  • Niet online

X-Lars

Just GoT it.

Dat kan alleen zonder anynomous functions (waarin je scope zou veranderen), dus je kan geen arguments meegeven:
JavaScript:
1
this.object.addEventListener('onclick', this.volgende, false);


In theorie kan je ook apply direct toepassen op addEventListener (maar niet op attachEvent in IE):

JavaScript:
1
this.object.addEventListener.apply(this.object, ['click', this.volgende, false]);

Dus, in de praktijk wat .oisyn zegt.

Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 22-09 16:37

.oisyn

Moderator Devschuur®

Demotivational Speaker

JavaScript:
1
2
3
4
5
6
7
8
9
10
11
12
Function.prototype.bind = function(vThis)
{
    var func = this;
    var args = Array.prototype.slice.call(arguments, 1);
    return function()
    {
        return func.apply(vThis, args.concat(Array.prototype.slice.call(arguments)));
    };
};


this.object.addEventListener('click', this.volgende.bind(this), false)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • X-Lars
  • Registratie: Januari 2004
  • Niet online

X-Lars

Just GoT it.

Ter verduidelijking, je kan dan dus ook arguments meegeven:
JavaScript:
1
this.object.addEventListener('click', this.volgende.bind(this, 'foo', 'bar'), false)

Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 22-09 16:37

.oisyn

Moderator Devschuur®

Demotivational Speaker

Idd. Als je dus doet: f = foo.bind(a, b, c), dan geeft dat een functie terug, en als je die zou aanroepen met f(d, e), dan wordt er dus eigenlijk a.foo(b, c, d, e) aangeroepen.

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • X-Lars
  • Registratie: Januari 2004
  • Niet online

X-Lars

Just GoT it.

Je zou dat kunnen zien als een soort van currying. Zie eventueel ook http://ejohn.org/blog/partial-functions-in-javascript/ voor meer relevant materiaal.

Aan de ene kant vind ik het een prachtig taaltje met dit soort kunstjes, maar aan de andere kant heeft dit soort constructies ook iets "hack" achtigs. Vnl. omdat je API niet direct uit de code op te maken valt. Het is wel heel krachtig in the end.
Pagina: 1