[js] Parameters aan callback functie meegeven.

Pagina: 1
Acties:
  • 102 views sinds 30-01-2008
  • Reageer

  • cyberstalker
  • Registratie: September 2005
  • Niet online

cyberstalker

Eersteklas beunhaas

Topicstarter
Ik probeer parameters aan de callback-functie van een Event Listener mee te geven. Het probleem is dat de callback-functie onderdeel is van een object.

In deze testcase stuur ik de 'caller' variabele mee, wat een link is naar het venster dat de titlebar wil maken. Vervolgens geef ik met een alert de titel van het venster weer.

De relevante code waar het om draait:
JavaScript:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function _titlebar(caller, title, width)
{
        var titlebar    = document.createElement('div');
        var textnode    = document.createTextNode(title);

        titlebar.setAttribute('class', 'titlebar');
        titlebar.setAttribute('style', 'width: '+width+'px;');
        titlebar.appendChild(textnode);

        titlebar.addEventListener('mousedown', function() { this.start_move(caller); }, false);
        titlebar.addEventListener('mouseup', this.stop_move, false);

        this._object    = titlebar;
}

_titlebar.prototype.start_move = function(caller)
{
        alert(caller._window_title);
}

Ik krijg de volgende foutmelding wanneer ik op de titlebar klik:
Fout: this.start_move is not a function
Bronbestand: http://martijntje.xs4all.nl/webdesk/script/general.js
Regel: 10
Het gaat dus om de volgende regel:
JavaScript:
1
titlebar.addEventListener('mousedown', function() { this.start_move(caller); }, false);


Ik kan dus geen gebruik maken van 'this' in die functie. Hoe kan ik nu een functie in mijn object gebruiken?

Wanneer ik een functie probeer aan te spreken buiten het object werkt het wel.

Ik ontken het bestaan van IE.


  • --MeAngry--
  • Registratie: September 2002
  • Laatst online: 11:05

--MeAngry--

aka Qonstrukt

Je kunt het proberen met:
JavaScript:
1
var _this = this;


Vlak voordat je this wilt gebruiken. Vervolgens gebruik je dan _this.

Wel niet vergeten dat je dan géén referentie hebt, maar een kopie van je huidige instantie. Voor zover ik uit m'n hoofd weet in ieder geval.

Dit dus:
JavaScript:
1
2
3
4
5
6
7
8
9
10
var _this = this;

titlebar.addEventListener('mousedown', function() { _this.start_move(caller); }, false);
titlebar.addEventListener('mouseup', _this.stop_move, false);

// Hier kan het dus fout gaan:
this._object    = titlebar;

// Dit werkt, maar is dus niet echt handig:
_this._object    = titlebar;

[ Voor 73% gewijzigd door --MeAngry-- op 06-04-2007 00:50 ]

Tesla Model Y RWD (2024)


  • chris
  • Registratie: September 2001
  • Laatst online: 11-03-2022
--MeAngry-- schreef op vrijdag 06 april 2007 @ 00:46:
Je kunt het proberen met:
JavaScript:
1
var _this = this;


Vlak voordat je this wilt gebruiken. Vervolgens gebruik je dan _this.

Wel niet vergeten dat je dan géén referentie hebt, maar een kopie van je huidige instantie. Voor zover ik uit m'n hoofd weet in ieder geval.
Je hebt wel een referentie, geen kopie. De code is goed, de uitleg verkeerd ;)

De techniek die --MeAngry-- beschrijft is het maken van een closure. Voor een technische gedetailleerde beschrijving, zie Javascript Closures. Voor een simpelere uitleg, zie Javascript Closures for Dummies.

  • Mitrilvich
  • Registratie: Juli 2004
  • Laatst online: 29-10 17:46
Het probleem met jou code is dat de betekenis van this is veranderd wanneer je event getriggerd wordt. Wanneer je event getrigged wordt heeft this de waarde van het calling object.

Je kan, zoals --MeAngry-- beschrijft, de benodigde variabelen globaal declareren zodat je er altijd bij kan komen.

Een andere optie heb je nog wanneer je gebruik maakt van de prototypejs library, dan kan je een functie aan een context binden. Simpel gezegd zorg je ervoor dat this voor die function dan vaststaat. Met prototypejs kan je dat zo doen:
JavaScript:
1
titlebar.addEventListener('mouseup', this.stop_move.bind(this), false); 

(weet niet wat de mogelijkheden zijn zonder prototypejs voor dit soort constructies)

[ Voor 7% gewijzigd door Mitrilvich op 06-04-2007 08:25 ]


Verwijderd

code:
1
2
var self = this;
titlebar.addEventListener('mousedown', function() { self.start_move.apply(self,[caller]); }, false)


dan verwijst "this" in de start_move method ook nog eens naar self. Het is me niet helemaal duidelijk wat je met die caller wil, maar wellicht wil je liever een method van die caller aanroepen?

code:
1
caller.method.apply(..etc..)

[ Voor 47% gewijzigd door Verwijderd op 06-04-2007 17:38 ]


  • crisp
  • Registratie: Februari 2000
  • Laatst online: 12:12

crisp

Devver

Pixelated

Ik gebruik tegenwoordig een afgeleide van prototype's bind:
JavaScript:
1
2
3
4
5
6
7
8
9
Function.prototype.bind = function()
{
    var handler = this, args = [].slice.call(arguments, 0), object = args.shift();

    return function()
    {
        return handler.apply(object, args.concat([].slice.call(arguments, 0)));
    }
}

te gebruiken als:

function.bind(scope-object[, parm1[, parm2[, ...] ] ]);

in dit geval krijg je dan zoiets (ik neem aan dat 'this' gewoon naar het HTML element moet verwijzen binnen start_move):
JavaScript:
1
titlebar.addEventListener('mousedown', this.start_move.bind(titlebar, caller), false);

start_move krijgt als gratis 2e parameter overigens ook het event-object mee in echte browsers :)

[ Voor 27% gewijzigd door crisp op 06-04-2007 20:17 ]

Intentionally left blank

Pagina: 1