En testant après qu'un utilisateur me fasse la remarque que mon code ne fonctionnait pas pour lui (/Firefox 1.5)
Et en cherchant j'ai trouvé ceci http://lists.w3.org/Archives/Public/public-webapi/2007Aug/0051.html
Ouch !
Et oui, si ce n'etait que F1.5, mais c'est visiblement aussi F2
Si cette version se doit d'être gérée (Gecko 1.8), à part une magouille de closure, je ne vois pas.
var http = new XMLHttpRequest(); http.open(...); http.onreadystatechange = (function(that) { return function() { if ( that.readyState == 4 ) { ... } }; })(http);
Et simplement, en utilisant la closure inhérante aux fonctions ?
http.onreadystatechange = function() { var that = http; if( that.readyState == 4 ) { ... } };
Mais je ne sais pas comment liberer correctement la reference à http Est-ce qu'un simple that=null et onreadystatechange=null suffisent ?
A+ Bol
Laurent vilday
Bol :
Salut Lolo ;-)
Hello :)
var http = new XMLHttpRequest(); http.open(...); http.onreadystatechange = (function(that) { return function() { if ( that.readyState == 4 ) { ... } }; })(http);
Et simplement, en utilisant la closure inhérante aux fonctions ?
http.onreadystatechange = function() { var that = http; if( that.readyState == 4 ) { ... } };
A priori oui c'est, grosso modo, pareil. Ca pourrait être une toute autre histoire si c'était dans une boucle, par exemple :
var http, i; for ( i = 0; i < 10; i++ ) { http = new XMLHttpRequest(); http.onreadystatechange = function() { // Erreur classique introduite par les closures. // Pour les 10 objets créés, "that" sera la référence // du dernier objet "http" créé. // Ce n'est pas le comportement désiré. var that = http; ... }; }
Ok c'est vrai que ça parait bizarre de créer en boucle des XMLHttpRequest(), mais bon c'est le principe qui compte :)
Tandis qu'avec la version que je t'avais proposé, ce genre de problème disparait parce que les contextes d'exécution sont "correctement" définis.
var http, i; for ( i = 0; i < 10; i++ ) { http = new XMLHttpRequest(); http.onreadystatechange = (function(that) { // ici that est toujours la référence // vers le bon objet "http" car le contexte est conservé. // C'est le comportement désiré. return function() { ... }; })(http); }
Je préfère la première version par habitude mais surtout parce que visuellement (et dans le temps quand faut maintenir) je pense que ça permet de bien mieux identifier qu'une magouille de contexte est utilisée à cet endroit.
Mais je ne sais pas comment liberer correctement la reference à http Est-ce qu'un simple that=null et onreadystatechange=null suffisent ?
that = null;
Oui je crois mais rien n'est moins sûr. Un simple "that = null;" à la fin du onreadystatechange devrait libérer la référence vers "http", mais comme toujours en js ça dépend beaucoup du contexte.
that.onreadystatechange = null;
Non, parce que de mémoire ça peut provoquer des erreurs selon les "vieilles" versions des différents navigateurs.
Lui préférer that.onreadystatechange = function(){};
Mais je pense que la meilleure façon de libérer la référence c'est la première proposition : that = null; à la fin du onreadystatechange.
-- laurent
Bol :
Salut Lolo ;-)
Hello :)
var http = new XMLHttpRequest();
http.open(...);
http.onreadystatechange = (function(that) {
return function()
{
if ( that.readyState == 4 ) { ... }
};
})(http);
Et simplement, en utilisant la closure inhérante aux fonctions ?
http.onreadystatechange = function() {
var that = http;
if( that.readyState == 4 ) { ... }
};
A priori oui c'est, grosso modo, pareil. Ca pourrait être une toute
autre histoire si c'était dans une boucle, par exemple :
var http, i;
for ( i = 0; i < 10; i++ )
{
http = new XMLHttpRequest();
http.onreadystatechange = function() {
// Erreur classique introduite par les closures.
// Pour les 10 objets créés, "that" sera la référence
// du dernier objet "http" créé.
// Ce n'est pas le comportement désiré.
var that = http;
...
};
}
Ok c'est vrai que ça parait bizarre de créer en boucle des
XMLHttpRequest(), mais bon c'est le principe qui compte :)
Tandis qu'avec la version que je t'avais proposé, ce genre de problème
disparait parce que les contextes d'exécution sont "correctement" définis.
var http, i;
for ( i = 0; i < 10; i++ )
{
http = new XMLHttpRequest();
http.onreadystatechange = (function(that) {
// ici that est toujours la référence
// vers le bon objet "http" car le contexte est conservé.
// C'est le comportement désiré.
return function()
{
...
};
})(http);
}
Je préfère la première version par habitude mais surtout parce que
visuellement (et dans le temps quand faut maintenir) je pense que ça
permet de bien mieux identifier qu'une magouille de contexte est
utilisée à cet endroit.
Mais je ne sais pas comment liberer correctement la reference à http
Est-ce qu'un simple that=null et onreadystatechange=null suffisent ?
that = null;
Oui je crois mais rien n'est moins sûr. Un simple "that = null;" à la
fin du onreadystatechange devrait libérer la référence vers "http", mais
comme toujours en js ça dépend beaucoup du contexte.
that.onreadystatechange = null;
Non, parce que de mémoire ça peut provoquer des erreurs selon les
"vieilles" versions des différents navigateurs.
Lui préférer that.onreadystatechange = function(){};
Mais je pense que la meilleure façon de libérer la référence c'est la
première proposition :
that = null; à la fin du onreadystatechange.
var http = new XMLHttpRequest(); http.open(...); http.onreadystatechange = (function(that) { return function() { if ( that.readyState == 4 ) { ... } }; })(http);
Et simplement, en utilisant la closure inhérante aux fonctions ?
http.onreadystatechange = function() { var that = http; if( that.readyState == 4 ) { ... } };
A priori oui c'est, grosso modo, pareil. Ca pourrait être une toute autre histoire si c'était dans une boucle, par exemple :
var http, i; for ( i = 0; i < 10; i++ ) { http = new XMLHttpRequest(); http.onreadystatechange = function() { // Erreur classique introduite par les closures. // Pour les 10 objets créés, "that" sera la référence // du dernier objet "http" créé. // Ce n'est pas le comportement désiré. var that = http; ... }; }
Ok c'est vrai que ça parait bizarre de créer en boucle des XMLHttpRequest(), mais bon c'est le principe qui compte :)
Tandis qu'avec la version que je t'avais proposé, ce genre de problème disparait parce que les contextes d'exécution sont "correctement" définis.
var http, i; for ( i = 0; i < 10; i++ ) { http = new XMLHttpRequest(); http.onreadystatechange = (function(that) { // ici that est toujours la référence // vers le bon objet "http" car le contexte est conservé. // C'est le comportement désiré. return function() { ... }; })(http); }
Je préfère la première version par habitude mais surtout parce que visuellement (et dans le temps quand faut maintenir) je pense que ça permet de bien mieux identifier qu'une magouille de contexte est utilisée à cet endroit.
Mais je ne sais pas comment liberer correctement la reference à http Est-ce qu'un simple that=null et onreadystatechange=null suffisent ?
that = null;
Oui je crois mais rien n'est moins sûr. Un simple "that = null;" à la fin du onreadystatechange devrait libérer la référence vers "http", mais comme toujours en js ça dépend beaucoup du contexte.
that.onreadystatechange = null;
Non, parce que de mémoire ça peut provoquer des erreurs selon les "vieilles" versions des différents navigateurs.
Lui préférer that.onreadystatechange = function(){};
Mais je pense que la meilleure façon de libérer la référence c'est la première proposition : that = null; à la fin du onreadystatechange.
-- laurent
Bol
Hello,
Mais je ne sais pas comment liberer correctement la reference à http Est-ce qu'un simple that=null et onreadystatechange=null suffisent ?
that = null;
Oui je crois mais rien n'est moins sûr. Un simple "that = null;" à la fin du onreadystatechange devrait libérer la référence vers "http", mais comme toujours en js ça dépend beaucoup du contexte.
<html><title><title><head> <script> var c=0; function init() { var o = {a:10}; document.links[0].onclick = function () { var _o = o; if(c==1)_o.a++; if(c==2)_o=null; if(c==4)o=null; alert('c='+c+' _o='+(_o?_o.a:'null')+' o='+(o?o.a:'null') ); c++; return false; }; alert('init'); } </script> </head> <body> <a href="#">=function(){}</a> <a href="javascript:init()">init()</a> </body> </html>
Tu remarqueras que : _o renait de ses cendres (via var _o=) o existe toujours et que c'est lui qu'il faut déreferencer (la closure de la fonction init)
Donc pour le cas de XHR precedent, ce n'est pas that qu'il faut déreferencer mais http, ... et c'est là mon probleme l'utilisation de this etait plus pratique car non lié à une reference nommée
A+ Bol
Hello,
Mais je ne sais pas comment liberer correctement la reference à http
Est-ce qu'un simple that=null et onreadystatechange=null suffisent ?
that = null;
Oui je crois mais rien n'est moins sûr. Un simple "that = null;" à la fin
du onreadystatechange devrait libérer la référence vers "http", mais comme
toujours en js ça dépend beaucoup du contexte.
<html><title><title><head>
<script>
var c=0;
function init() {
var o = {a:10};
document.links[0].onclick = function () {
var _o = o;
if(c==1)_o.a++;
if(c==2)_o=null;
if(c==4)o=null;
alert('c='+c+' _o='+(_o?_o.a:'null')+' o='+(o?o.a:'null') );
c++;
return false;
};
alert('init');
}
</script>
</head>
<body>
<a href="#">=function(){}</a> <a href="javascript:init()">init()</a>
</body>
</html>
Tu remarqueras que :
_o renait de ses cendres (via var _o=)
o existe toujours et que c'est lui qu'il faut déreferencer
(la closure de la fonction init)
Donc pour le cas de XHR precedent, ce n'est pas that
qu'il faut déreferencer mais http, ... et c'est là mon probleme
l'utilisation de this etait plus pratique car non lié à une reference
nommée
Mais je ne sais pas comment liberer correctement la reference à http Est-ce qu'un simple that=null et onreadystatechange=null suffisent ?
that = null;
Oui je crois mais rien n'est moins sûr. Un simple "that = null;" à la fin du onreadystatechange devrait libérer la référence vers "http", mais comme toujours en js ça dépend beaucoup du contexte.
<html><title><title><head> <script> var c=0; function init() { var o = {a:10}; document.links[0].onclick = function () { var _o = o; if(c==1)_o.a++; if(c==2)_o=null; if(c==4)o=null; alert('c='+c+' _o='+(_o?_o.a:'null')+' o='+(o?o.a:'null') ); c++; return false; }; alert('init'); } </script> </head> <body> <a href="#">=function(){}</a> <a href="javascript:init()">init()</a> </body> </html>
Tu remarqueras que : _o renait de ses cendres (via var _o=) o existe toujours et que c'est lui qu'il faut déreferencer (la closure de la fonction init)
Donc pour le cas de XHR precedent, ce n'est pas that qu'il faut déreferencer mais http, ... et c'est là mon probleme l'utilisation de this etait plus pratique car non lié à une reference nommée