Javascript

Une section dédiée au javascript, avec qq trucs et Trucs et astuces javascript

J'ajoute ici qq concept de base que j'aurais aimé qu'on m'expose plus tôt. Il s'agit de choses +/- passées sous silence dans les exposés sur le javascript, mais qui me semblent fondamentales pour comprendre le langage, et même si on ne les utilise jamais c'est très utile pour lire le code des autres.

En fait, je n'aimais pas ce langage bizarre qui permettait de faire tout et n'importe quoi n'importe comment et donc donnait souvent des trucs impossible à debuguer. C'est juste que j'avais pas compris ce qu'était une fonction (entre autres)…

Il ne s'agit donc pas du tout d'un tutoriel pour apprendre le langage, juste un pointage de particularités de ce langage. Attention, c'est pas forcément très didactique pour un débutant, le but est de soulever ces particularités, pas de les expliquer, donc z'êtes prévenus, venez pas m'accuser ensuite d'avoir ajouté de la confusion en soulevant des pbs sans y répondre. Y'a plein de littérature pour les réponses, encore faut-il savoir qu'il pourrait y avoir des questions.

Tous les bouts de code peuvent être copiés / collés dans une console firebug

Objets et fonctions

Une fonction est un objet (elle peut avoir des propriétés et méthodes !) qui a en plus, par rapport à un objet "classique" :

  • un corps, c'est le code qui s'exécutera si on appelle cette fonction avec des parenthèses (on peut ajouter une liste d'arguments séparés par des virgules à l'intérieur de ces parenthèses).
  • un contexte d'exécution (le this dans le corps de la fonction)

Constructeur

C'est une fonction comme une autre censée renvoyer un objet (c'est pour ça qu'on l'a appelée comme ça), qu'on est censé appeler avec "new". Pour la distinguer à la lecture, et par cohérence avec les autres langages on la nomme en général avec une majuscule et on parle de classe. Par ex

// un constructeur
function Truc(nom, contenu) {
  this.nom = nom || "anonyme";
  this.contenu = contenu || "";
  return this;
}
 
var truc1 = new Truc("1er truc", "avec une chaine de caractère dedans");
// mais on aurait pu aussi faire
var truc2 = {};
Truc.call(truc2, "2e truc", "avec une autre chaine"); // on donne un objet vide en contexte de la fonction, les autres paramètres deviennent les arguments de cette fonction
// ou encore l'écrire littéralement
var truc3clone2 = {nom:"2e truc", contenu:"avec une autre chaine"}
var truc4clone2 = new Truc("2e truc", "avec une autre chaine");
console.log(truc1 , truc2, truc3clone2, truc4clone2);
// c'est vraiment pareil ?
console.log("truc2 == truc3clone2 ? " +(truc2 == truc3clone2));
console.log("truc2 == truc4clone2 ? " +(truc2 == truc4clone2));
console.log("truc3clone2 == truc4clone2 ? " +(truc3clone2 == truc4clone2));
// évidemment avec === c'est encore moins vrai

prototype

Dans l'exemple précédent, le résultat avec et sans new semble identique, mais pas tout à fait, la console de firebug nous dit que truc1 est un "Truc" alors que truc2 est un "Object", comme ce sont tous les deux des typeof "object", ça change quoi ?

// la preuve que ma fct Truc est aussi un objet, il a une propriété "prototype" à laquelle j'ajoute une méthode ajouterMachin
Truc.prototype.ajouterMachin = function(valeurMachin) {
  this.machin = valeurMachin;
}
truc1.ajouterMachin("bof");
console.log(truc1);
truc2.ajouterMachin("rebof");
console.log(truc2);

Donc, être un Truc (plutôt qu'un Object) permet de profiter du prototype de truc.

Le prototype d'une fonction permet d'ajouter en cours de route des méthodes à tous les objets qu'elle a pondu avant. Ça revient à ajouter dynamiquement des méthodes à une classe, méthodes qui vont s'appliquer à tous les objets de cette classe, même ceux qui ont été instanciés avant la création de cette nouvelle méthode. Étonnant non ?

Ça marche évidemment pour modifier en cours de route ce que fait une méthode qui existait déjà.

Évidemment, vaut mieux pas abuser de la redéfinition, parce que cela devient plus difficile à débuguer quand la même méthode sur les mêmes objets fait des choses différentes suivant le moment et le contexte.

De plus, le code d'une méthode ajouté via le prototype est commun à tous les objets.

Portée / contexte

Les variables sont locales à une fonction, mais pas à un bloc. Par ailleurs, à l'exécution tout se passe comme si le moteur js mettait toutes les déclarations "var maVariable…" ou "function maFonction…" au début de la portée puis lançait ensuite l'exécution, ce qui permet d'utiliser des variables/fonctions pas encore déclarées, mais peut surprendre à première vue, par ex

function truc() {
  var tata = 1
  console.log(toto); // ça plante pas, toto existe même si sa valeur n'est pas définie
  if (tata > 2) {
    var toto;
  }
}
truc()

Fonction anonymes

à poursuivre

 
javascript/start.txt · Dernière modification: 05/06/2012 14:52 par daniel