11548 sujets

JavaScript, DOM et API Web HTML5

Bonjour a tous,

J'ai un petit problème sur un objet javascript que je suis entrain d'implémenter, je désierais utiliser le nom de mon objet une fois initialiser dans un gestionnaire d'evenement:

mise en situation


var data = new containerdata() //mon objet
data.afficher() //methode de mon objet


(je vais volontairement zapper la compatibilité ie/ff/opera/etc.. car ca n'est pas le problème)

le code de mon objet


function datacontainer()
{
this.data = 0;

this.evthandler(toto)
{
alert(toto);
}

this.afficher = function()
{
var table = document.createElement('table');
var tbody = document.createElement('tbody');

//etc pour faire un tableau formater conforme au DOM comportant tr,th,td
//et donc le problème

var tadaa = 'tidilidatidi';

th.addEventListener("onclick", [b]this.evthandler(tadaa)[/b],false);

}
}


Bien evidement c'est une version simplifier de mon fichier mais l'idée est la, je n'arriver pas a ajouter le nom (data) de mon objet initialiser a mon evenement, le 'this' est evidement faux, lors du click, l'objet this n'existe pas (forcement on est plus dans l'objet).

Si vous avez des idées je suis preneur ^^
Merci
bonjour ,

et hola tous ces " this " ...ons'y perd

Si tu veux utiliser une fonction qui en arguments passe uen autre fonction ,
le 'binding ' ( contexte d'exécution ) est "perdu" .. Smiley murf

Il faut passer par une méthode de l'objet Function (mère de tout nos fonctions Smiley lol ) appelée 'Call' (il existe également 'apply qui différe par les arguments passé à la fonction) ...

bon ok un exemple

// un objet 
var containerdata = {
     data : 'une valeur',
    evthanler : fonction() {
       /// tes instructions
       }
   }
function binding(fx,obj) {
    // la fonctin passée en paramétre utilise sa methode call
   // pour préciser son contexe 
   fx.call(obj);
   }

//appel de fonction 
binding(containerdata.evthanler,data);


voilà un peu comment utilise cette propriété de l'objet Function

Ps: essaie toujours bien de savoir qu'elle est l'objet qui apelle la méthode (et qui devient valeur de 'this') et attention au méthode de l'objet global tel 'alert' où
par exemple dans this.alert => this est toujours l'objet globale window !!!

Avance méthode par méthode en déterminant la valeur de l'objet appelé par la méthode utilisée ( fait un alert à chaque fois pour t'en assurer et 'encapsule ' ces valeurs dans leur fonction avec par exemple

function untel() {
  var contexteCourant = this;
  var methode_objet = function(contexteCourant) {
      this.prop = valeur;
      this.autreMethode = methode
     ....ect
    }
}

function methode() {
  // instructions
  }
... ect


... mais je m'emballe un peu Smiley rolleyes
j'espère que cela pourra un peu t'aider
Merci pour cette réponse rapide,

j'ai chercher un peu de mon coté également et j'ai trouver cette méthode de nommage qui marche parfaitement sous IE et qui me permet de passer le nom de l'objet instancier dans ma fonction sans "this".

Elle fait appelle également a la fonction mère Function pour appeler ma méthode.


//dans mon objet ajout d'une propriété contenant le nom de mon instance.

this._name = 'data' // data dans le cas de mon exemple

//puis pour un element HTML

HTMLobject.onclick = new Function( "return "+this._name+"._order(this)" );


Je peux grâce a cette syntaxe reunir tout ce dont j'avais besoin,
- le remplacement de this (mon objet) par son instance
- utiliser le this qui réfère a l'objet HTML

Je vais aprofondir ton idée également car plus "propre" et surtout compatible pour tous les naviguateurs apparement.

Merci beaucoup
En plus avec cette ligne, tu commets une double erreur :

th.addEventListener("onclick", this.evthandler(tadaa),false);  

1 - Tu n'appelles pas la fonction lors de l'évènement, mais directement à l'affectation de l'évènement. Tu devrais d'ailleurs logiquement obtenir une alerte dès l'affichage de ce tableau.
Détails : evthandler(...) appelle la fonction immédiatement. Elle ne retourne rien, tu attribues donc une hypothétique fonction undefined à l'évènement. Ca doit également te valoir une jolie erreur.
Suggestion : remplacer fonction(arguments) par function() { fonction(arguments) }

2 - Comme déjà évoqué, tu perds le contexte d'objet (le this).
Solution : Utiliser Function.apply ou Function.call grâce à un code similaire à celui-ci :

var selfref = this;
var fnc = function () {
selfref.apply(selfref, arguments);
}
this.addEventListener("click", fnc, false);


Explications : On crée une variable auto-référente sur elle-même, pour qu'on puisse l'utiliser dans la fonction qui suit (si on avait utilisé this, on n'aurai pas réglé le problème!)
Ensuite on crée une fonction qui se chargera simplement d'attribuer le contexte d'objet correct pour exécuter la fonction qui réagit à ton évènement, ici j'ai pris l'exemple avec onclick et addEventListener mais ça marche avec n'importe quel autre évènement, avec attachEvent pour IE, et enfin on change la ligne d'attribution de l'évènement pour appeler notre fonction qu'on vient de créer.
Je sais, c'est peut-être pas évident de capter ce que fait mon script exactement.

Une fonction permettant d'appliquer ce principe de manière général va arriver plus tard dans ce post.

EDIT : Non, mieux : je crois que je vais directement écrire un tuto, parce que ce n'est pas de la tarte à expliquer le pourquoi du comment. Instances supérieures, votre avis?
Modifié par QuentinC (19 Jul 2007 - 17:04)
QuentinC a écrit :

EDIT : Non, mieux : je crois que je vais directement écrire un tuto, parce que ce n'est pas de la tarte à expliquer le pourquoi du comment. Instances supérieures, votre avis?


... me tarde de le lire ! Smiley cligne

Malgré les nombreux tests et exercices que je fais , j'ai bien du mal parfois avec certaine partie de script (comme je pense que je ne vais pas tarder à poster concernant les différences entre propotype et méthode de classe ... Smiley lol ) , ....

.... et un bon tuto n'est jamais de trop ! enfin c'est mon avis de instance non supérieure ... un peu instance 'locale quoi Smiley lol
Modifié par kzone (19 Jul 2007 - 20:34)
Bah je sais pas si ça va aboutir, étant donné que plus de 95% de ce que je commence, je ne le finis jamais. Ah le défaut universel du programmeur...
QuentinC a écrit :
Ah le défaut universel du programmeur...

COPAIN !

Sinon au sujet des variables auto-référentes, ça risque de faire un memory-leak sous notre ami IE, l'idéal serait de virer une des références lors du unload
FlorentG > Tu peux donner plus de détails à propos de ce prétendu memory-leak ? je n'ai jamais entendu parler de ça.
Merci a tous pour vos conseils, mais QuentinC, ton code


var selfref = this;

var fnc = function () {

selfref.apply(selfref, arguments);

}

this.addEventListener("click", fnc, false);


le fait de definir une nouvelle variable selfref copiant l'objet courant n'est pas un peu lourd, dans ce cas j'aimerais assez éviter de recopier la totalité de la variable.

Néanmoins, j'ai peut être mal compris, pour moi tu contourne le problème du this en réinstanciant la variable dans un nom que le navigateur pourra interpreter, tu ne te sert plus de l'objet "père" si je puis dire.
Smiley confus

Comme dit plus haut je ne sait pas si ma compréhension est au top mais ca me fait cette effet la, mon objet étant bien evidement pas fait pour renvoyer alert(..) Smiley lol et contient les donnée d'une base mssql, ne pas le recopier pourrais être plus propre non???

PS: Je pense que la méthode (bien que beaucoup moins propre que les votre je vous l'accorde) ne fait que créer une fonction anonyme qui renvoit le nom de l'objet instancier et sa méthode

Je suis dans le doute la ^^
OverZeFourbe a écrit :
Merci a tous pour vos conseils, mais QuentinC, ton code


var selfref = this;

var fnc = function () {

selfref.apply(selfref, arguments);

}

this.addEventListener("click", fnc, false);


le fait de definir une nouvelle variable selfref copiant l'objet courant n'est pas un peu lourd, dans ce cas j'aimerais assez éviter de recopier la totalité de la variable.

Javascript devrait être assez intelligent pour ne créer qu'une référence.
En général, les objets sont toujours passés par référence. La seule exception que je connais est le C/C++...où il faut le spécifier explicitement.


a écrit :

Néanmoins, j'ai peut être mal compris, pour moi tu contourne le problème du this en réinstanciant la variable dans un nom que le navigateur pourra interpreter, tu ne te sert plus de l'objet "père" si je puis dire.
Smiley confus

Comme dit plus haut je ne sait pas si ma compréhension est au top mais ca me fait cette effet la, mon objet étant bien evidement pas fait pour renvoyer alert(..) Smiley lol et contient les donnée d'une base mssql, ne pas le recopier pourrais être plus propre non???

Ben comme je disais plus haut, en principe les données ne sont pas copiées. Le problème du this est que c'est un pointeur variable qui se modifie en fonction du contexte, ici le but est de créer une sorte de pointeur qui ne se modifie plus pour être sûr qu'on pointe sur le bon objet. Une sorte de const *, sans doute.
Bon, je crois que je vais arrêter avec mes analogies tangeantes.
QuentinC a écrit :
FlorentG > Tu peux donner plus de détails à propos de ce prétendu memory-leak ? je n'ai jamais entendu parler de ça.

Sous Internet Explorer, le garbage-collector (le bout de logiciel chargé de vider les variables plus utilisées) utilise la méthode du comptage de référence : dès qu'une variable est référencée par une autre, on incrémente un chiffre. Maintenant dès que la référence n'est plus utilisée, on décrémente. Quand ça revient à zéro, on considère que la variable n'est utilisée par plus personne, on peut la virer.

Exemple pour illustrer le principe :
var obj = {
  chaine: 'bla bla'
};

var obj1 = {
  o: obj;
};

var obj2 = {
  p: obj
};

Là on voit que l'objet obj est référencé deux fois, par obj1 et obj2. Si on quitte la page, IE va essayer de virer toutes les variables.

Il va essayer de virer obj, mais ne pourra pas, à cause des deux références. Il passera à obj1, qui pourra être supprimé. Il le vire, vire aussi la référence à obj, et décrémentera le nombre de référence de obj. Re-bellotte pour obj2. Là maintenant le nombre de références de obj passera à 0, il pourra le virer aussi, magie Smiley smile


Avec une référence circulaire, le nombre de références restera toujours à 1, et du coup même si on quitte la page, la variable ne pourra pas être supprimée Smiley decu Si l'objet est lourd et qu'on visite un grand nombre de pages du même site, la conso mémoire augmentera.

Exemple :
var obj = document.getElementById('pouet');

document.getElementById('pouet').machin = obj;

Là l'objet obj a une propriété qui pointe sur lui-même. argh. Lorsque IE va vouloir supprimer la variable, il verra qu'il y a une référence. Donc ne pourra pas le virer Smiley decu

La solution est de mettre quelque part, lors du unload par exemple, un :
document.getElementById('pouet').machin = null;

Là ce sera bon Smiley smile


Il y a plein d'autres leaks possibles, avec les closures et d'autres cas. Voir sur Understanding and Solving Internet Explorer Leak Patterns (anglais). Cette histoire de références circulaires existe dans d'autres langages, en PHP par exemple.
Aha, je comprends mieux pourquoi après avoir visité certains sites iexplore.exe me prend 80 Mo de RAM voire plus, alors qu'en général ça tourne entre 20 et 30.

Mais rassure-moi, quand on quitte IE, toute la mémoire même celle victime de ce bug est libérée ?
QuentinC a écrit :
Mais rassure-moi, quand on quitte IE, toute la mémoire même celle victime de ce bug est libérée ?

Ouais, c'est le seul moment ou la totalité de la mémoire utilisée par IE est libérée
Merci pour toutes ces précision sur les 'memory-leak' ... je comprends un peu mieux
ce procession javascript !

J'avais trouvé quelque infos cette nuit , mais j'avais jusque là pas trop saisi ...

Enfin il va falloir que j'approndisse un peu Smiley lol



QuentinC a écrit :

En général, les objets sont toujours passés par référence. La seule exception que je connais est le C/C++...où il faut le spécifier explicitement.

... et le PHP il me semble également avec l'opérateur & ...!?
a écrit :

... et le PHP il me semble également avec l'opérateur & ...!?

Pour les variables et tableaux, oui. Pour les objets je ne crois pas.
En même temps je n'ai quasiment jamais fait de POO en php...
QuentinC a écrit :
Pour les variables et tableaux, oui. Pour les objets je ne crois pas.

Effectivement, mais ça ne vaut que pour PHP5. En PHP4, même pour les objets il faut spécifier &
Salut,

Petite précision quand même : la fuite de mémoire n'existe pas pour chaque référence circulaire, et heureusement, sinon IE mangerait une quantité de mémoire monstrueuse... En fait, la fuite de mémoire apparaît en cas de référence circulaire entre un objet du DOM et un objet JavaScript.
Modifié par Julien Royer (23 Jul 2007 - 09:45)