JavaScript / JQuery




Expertise (5/5)



J'utilise régulièrement JavaScript depuis 2 ans. J'ai développé de nombreux greffons pour JQuery.

Ce document contient quelques exemples simples de réalisation.


Javascript: la portée des variables

La portée des variables déclarées dans une fonction est limitée à la fonction. Mais, contrairement à d’autres langages (C, C++, Java, GO...), la portée des variables déclarées dans un bloc ({...}) n’est pas limitée au bloc. De nombreux développeurs sont spécialisés dans des langages tels que C, C++ ou Java et ce dernier point peut engendrer de nombreuses erreurs: en déclarant des variables dans des blocs, ils pensent que la portée de ces dernières est limitée aux blocs dans lesquels sont déclarées. C'est faux.

Le script ci-dessous utilise une fonction anonyme pour « isoler » les variables utilisées dans le bloc d’une boucle.


La variable x n'est pas définie en dehors de la boucle. En revanche la variable i est définie. Pour limiter la portée de la variable i on peut utiliser une fonction anonyme de la façon suivante:


Note importante sur le processus de "déclaration implicite":

la déclaration d'une variable peut être effectuée de façon implicite lors de la première assignation d'une valeur à une variable (sans utilisation du mot clé var).

Par exemple

        var i = 0; // Déclaration explicité de la variable i.
        var f = function() {
            x = 10; // Déclaration **implicite** de la variable x.
        };
        
Ce mécanisme de déclaration implicite est la cause de très nombreux dysfonctionnements extrêmement difficiles à diagnostiquer. En effet, il est très facile d’oublier d’utiliser le mot clé var. Et, dans ce cas, l’interpréteur JavaScript ne lance aucun avertissement.

L’interpréteur va « remonter » les « zones de portées des variables » à la recherche de la variable.

Illustration:


Traitement de la variable x:

Traitement de la variable y:

Résultat à l'exécution:


Le "hoisting"

Le "hoisting" (to "hoist" peut être traduit pas "hisser" ou "lever") est une caractéristique originale du JavaScript. Ce mécanisme, s'il n'est pas bien compris par le développeur, peut engendrer des erreurs extrêmement difficiles à détecter.

Le "hosting" consiste à déplacer les déclarations des variables au début des blocs qui délimitent leurs portées.

Autrement dit:


Est équivalent à:


Mais, attention, ce n'est pas équivalent à:


Note importante sur le mécanisme de "hoisting": le mécanisme de "hoisting" produit parfois des effets difficiles à prédire.


Résultat à l'exécution:


Vous constatez le message suivant:

ERROR: y is not defined (you should understand: y is not **declared**)
Les closures

Wikipedia: http://fr.wikipedia.org/wiki/Fermeture_%28informatique%29

Dans un langage de programmation, une fermeture ou clôture (en anglais : closure) est une fonction qui capture des références à des variables libres dans l'environnement lexical. Une fermeture est donc créée, entre autres, lorsqu'une fonction est définie dans le corps d'une autre fonction et fait référence à des arguments ou des variables locales à la fonction dans laquelle elle est définie.

La nature asynchrone du JavaScript rend indispensable l’utilisation des closures. En effet, entre le moment où un gestionnaire d’évènement est exécuté, et le moment où il a été préalablement défini, les valeurs des variables utilisées par le gestionnaire peuvent avoir été modifiées. Il est donc indispensable de « capturer » la valeur d’une variable à un instant T afin de pouvoir utiliser cette valeur ultérieurement. Pour cela on utilise la construction suivante :


    var eventHandler = function(valueToCapture1, valueToCapture2) {
        return function() {
            // Use the captured values.
            console.log("(valueToCapture1, valueToCapture2) = " + valueToCapture1, valueToCapture2);
        };
    }
    

Exemple d'utilisation


ou:


Dans le code "handlers.push(eventHandler(i*2, object))", "i*2" est transmis pae copie. En revanche "object" est transmis par référence. Mais à chaque appel à la fonction "setTimeout()", une nouvelle référence est transmise. Ainsi les fonctions retournées par l'appel à "eventHandler()" utilisent des instances distinctes d'objets.

Le code "var object = { a: i }" signifie que la valeur de "object" est une référence vers un objet.

A chaque passage dans la boucle, "object" prend une nouvelle valeur (car un nouvel objet - "{ a: i }" - est créé).

Ainsi, à chaque appel de la fonction "eventHandler()", le paramètre "valueToCapture2" (qui est une référence vers l'objet "object") prend une nouvelle valeur.

Résultat à l'exécution:


Remarque sur l'utilisation d'objets (passage par référence)

Maintenant, cosidérons le code ci-dessous:


Résultat à l'exécution:


Contrairement à l'exemple précédent, on constate que la valeur affichée de "valueToCapture2.a" ne change pas (elle vaut 2). Cette valeur correspond à la valeur de "i" lors du dernier passage dans la boucle.

Explication: contrairement à ce qui se passe dans l'exemple précédent, la valeur de "valueToCapture2" ne change pas d'un passage à un autre dans la boucle. Cette valeur est égale à la référence de l'objet "object".

Pour obtenir le comportement "attendu", une solution serait de créer un clone de l'objet object, comme dans l'exemple ci-dessous.


Constructeurs et prototypes

Cette section présente deux techniques pour la création d’objets :

Technique 1: avec prototype


Technique 2: sans prototype


Ces deux techniques ne sont pas équivalentes. Elles diffèrent, principalement, sur deux points :

Illustration:


A l'exécution:


Héritage

Le code ci-dessous présente deux techniques qui permettent de faire hériter un objet des propriétés et des méthodes d’un autre objet.


A l'exécution:


Et:


Ces deux techniques ne sont pas équivalentes. Veuillez consulter la rubrique Constructeurs et prototypes.
Un trombinoscope animé

Cet exemple illustre une utilisation du greffon. Une série de 6 images défile sur trois "cases".


 
 

Code du greffon


Utilisation

Création de la zone d'affichage des images

Une image est affichée dans un "bloc DIV". Ce bloc est identifié par son nom, associé à l'attribut "id". Le code ci-dessous crée trois blocs alignés horizontalement. Chaque bloc est utilisé pour afficher une image.


Création du trombinoscope


Chargement du Javascript et démarrage du trombinoscope

L'utilisation du greffon de trombinoscope nécessite le chargement de l'excellent greffon suivant :

https://github.com/farinspace/jquery.imgpreload


Créer des liens

Ce greffon très simple permet d'appliquer des liens sur des zones du document.

Un lien sur une image:


Code du greffon


Utilisation

Pour associer un lien à un élément du document, il suffit d'ajouter à l'élément un attribut dont la valeur pointe vers le lien désiré. Dans le code ci-dessous, nous avons choisi d'utiliser l'attribut "link". Le choix du nom de l'attribut est arbitraire. Ce nom sera utilisé lors de l'activation du code Javascript (le nom de l'attribut sera passé en argument au greffon).

Création de la zone d'affichage des liens


Chargement du Javascript et démarrage


Initialisation de l'API Google pour un site multi-domaine

Il est courant d'associer plusieurs noms de domaines à un même site. Or, les clés d'utilisation de l'API Google sont liées à un seul nom de domaine. Le code ci-dessous permet une initialisation de l'API Google quel que soit le nom de domaine utilisé.


Calcul d'un âge, à partir d'une date de naissance

Si vous développer un site communautaire, il peut être intéressant de déporter les calculs des âges de vos membres sur le client.


Sliders

Code du greffon


Démonstration

Note: Les liens "précédent" et "suivant" peuvent être remplacés par des images, des boutons... Ces liens peuvent être disposés n'importe où sur le document.

 
Précédent
Suivant
 

 
 

 
Précédent
Suivant
 

 
 

Utilisation

Création des zones de défilement

Les diapositives sont définies dans une liste non indexée.


Les contrôles de défilement sont identifiés par leur ID, construit à partir de l'ID de la zone de défilement des diapositives. Si "IZ" est l'ID de la zone de défilement des diapositivesn alors :

La direction de défilement est définie par la valeur de l'attribut "direction".

Première zone : défilement horizontal


Seconde zone : défilement vertical


Chargement du Javascript et démarrage


Note: Le sélecteur JQuery ("[slider]", en l'occurrence) est déterminé en fonction des noms des attributs associés aux zones de défilement des diapositives. Dans cet exemple, les deux zones de défilement se voient attribuer le même attribut ("slider", en l'occurrence). Ceci n'est pas une obligation. Il est possible d'attribuer des attributs différents. Dans ce cas, la méthode devra être appelée autant de fois qu'il y a d'attributs différents.


Ajax

Le code ci-dessous illustre l’utilisation de Jquery pour le chargement de données et de code à exécuter.


js_to_load_and_execute.js


json_to_load_and_execute.js