JavaScript
Bases du langage et son évolution

Minh hai Nguyen, Sylvain Pollet-Villard
7 novembre 2011

Javascript, origines du langage

Historique des technologies Web
  • 1991 HTML
  • 1994 HTML 2
  • 1996 CSS 1 + JavaScript
  • 1997 HTML 4
  • 1998 CSS 2
  • 2000 XHTML 1
  • 2002 Tableless Web Design
  • 2005 AJAX
  • 2009 HTML 5 = HTML 5 + CSS 3 + JavaScript & nouvelles APIs

Bases du langage

JavaScript a été conçu pour rendre les pages Web plus dynamiques et interactives.

Les scripts sont des fichiers texte contenant le code source directement interprété par le navigateur du client.

Le client dispose du code source et peut le modifier avant ou pendant l'exécution avec les bons outils. Il est possible d'ajouter ou d'écraser du code Javascript à tout moment dans n'importe quelle page Web.

Des outils comme Greasemonkey permettent d'appliquer automatiquement un code Javascript personnalisé au chargement d'une page prédéfinie pour modifier son contenu ou son comportement.

Comment ajouter du JavaScript à une page web ?

JavaScript, un langage 100% objet

Tout est objet ou référence à un objet: les variables, les tableaux, les fonctions; excepté les primitives number, string, boolean souvent encapsulées dans leurs équivalents objets, et undefined pour l'inexistence.

  typeof true; // boolean
  var str = "Hello JavaScript !"; typeof str; // string
  var str2 = new String(str); typeof str2; // object
  str2 == str; //true ; égalité par valeur
  str2 === str; //false ; égalité par valeur ET par type 
  
  var whatsyourname = function(nom){ return "My name is "+nom; };
  typeof whatsyourname; // function
  
  var tab = [0,"1",function(){ return 2; }];
  typeof tab // object
  tab[0] == 0; tab[1] == 1; tab[2]() == 2; tab[3] == undefined // all true

Manipulation d'objets : Object Litteral Notation

var company = {
   name: "Ninjavascript",
   boss: {  name : "Bill",
            salary : 8000   },
   makeAdvertisement:function(){ alert('Ninjavascript rocks !'); }
};

company.makeAdvertisement();
company.boss.name;
company["boss"]["salary"];

Scopes, variables locales et globales

  // Par défaut, les objets sont définis dans le scope global

  var a=0;
  function factorielle(nombre) { // ou window.factorielle
    var result=1; // variable locale
    b=2;
    for(var i=1; i<=nombre; i++){ result*=i; }
    return result;
  }

  a === window.a;
  factorielle === window.factorielle;

  result === undefined // result est une variable locale de factorielle
  b === window.b // en omettant var, b a été déclaré global

Le mot-clé this

En Java, this désignait dans une classe l'instance courante de cette classe.

En JavaScript, this désigne l'objet correspondant au scope actuel.

call et apply permettent d'appeler une fonction en spécifiant le scope à l'éxécution (autrement dit this) et les arguments passés à l'appel.

function findStupidNickName(){
	this.nickname = "KickAss"; //who is this ???
	console.log(this) // unmask the hero
}

var Jack = { realName: "Jack Ass", becomeAHero: findStupidNickName };
var John = { realName: "John Smith" };

findStupidNickName(); //this is window ! BSOD kick ass !
Jack.becomeAHero(); //this is Jack ! I knew it !
findStupidNickName.call(John); //this is John !

Manipulation d'objets : Objets mutables

Les objets sont totalement mutables. Cela signifie qu'on peut modifier, ajouter ou enlever ses propriétés à tout moment par simple affectation. Le type d'une variable est redéfini à chaque affectation.

var hi = "Hello !";
hi = 83110;
hi = ["H","e","l","l",0] ;
hi = function(){ alert("Hello !"); };

//Ajout de propriétés/méthodes à un objet
company.name="Ninjavascript & Co";
company.boss.makeBusiness = function(){ this.salary += 1000; };
company["makeAdvertisement"] = company.boss.makeBusiness;

Constructeurs

JavaScript ne propose pas de classes mais des fonctions spécifiées comme constructeurs. En préfixant l'appel d'une fonction par le mot-clé new, on indique que la fonction doit se comporter comme un constructeur et instancier un nouvel objet avec les membres définis par cette fonction. A l'intérieur du constructeur, le mot-clé this fait référence à l'instance créée.

function Car(model, miles){
   this.model = model;
   this.miles  = miles;
   this.toString = function(){
   	return this.model + " has done " + this.miles + " miles";
   };
}
 
var civic = new Car("Honda Civic", 20000);
var mondeo = new Car("Ford Mondeo", 5000);
civic.toString(); // "Honda Civic has done 20000 miles"
civic.constructor === Car;

Prototypes

Toutes les fonctions JavaScript ont une propriété prototype. Quand on appelle un constructeur, toutes les propriétés du prototype du constructeur sont rendues accessibles au nouvel objet créé. Ainsi, plusieurs objets Car sont créés et ont accès au même prototype. C'est donc une manière de faire de l'héritage en Javascript ou encore de définir des variables statiques communes à toutes les instances.

function Car(model, miles){ this.model = model; this.miles  = miles; }

Car.prototype.numberOfWheels = 4;
Car.prototype.toString = function(){
    return this.model + " has done " + this.miles + " miles";
};

var civic = new Car("Honda Civic", 20000);
var limousine = new Car("Limousine Deluxe 6 roues",0);
limousine.numberOfWheels = 6;
civic.numberOfWheels === 4; limousine.numberOfWheels === 6;

Exemple complet d'objet

var company = {
    name: "Ninjavascript",
    employees: [],
    boss: {
        name : "Bill Jobs",
        salary : 8000,
        enroll : function(name){
            var newGuy = new company.Employee(name);
            company.employees.push( newGuy );
            return newGuy; 
        }
    },
    Employee: function(name){ this.name=name; this.salary = company.boss.salary / 10; },
};

var Bill = company.boss, Thomas = Bill.enroll("Thomas Anderson");
company.Employee.prototype.work = function(){ return (this.name + ": M'kay boss !"); };
Thomas.work(); // "Thomas Anderson: M'kay boss !"
Thomas.salary === 800;

Un rappel sur le DOM (Document Object Model)

<html>
     <head>
           <title>Sample Document</title>
     </head>
     <body>
           <h1> An HTML Document</h1>
           <p id="paragraphe">This is a <i>simple</i> document</p>
     </body>
</html>

DOM : Accès et manipulation en Javascript

document est un objet du scope global dans toute page Web

Accéder aux éléments

Modifier les éléments

DOM : Accès et manipulation

Naviguer entre les éléments

Insérer / supprimer des éléments

DOM : Exemple d'insertion de contenu en JavaScript

var lien = document.createElement("a");
var texte_lien = document.createTextNode("isen");

lien.id = "link_isen";
lien.setAttribute("href" , "http://www.isen.fr");

lien.appendChild(texte_lien);
document.getElementById("paragraphe").appendChild(lien);

Les principaux évènements sur le DOM

Gestion des évènements

A la suite d'un évènement, un objet Event contenant des données spécifiques à l'évènement se propage dans l'arbre DOM en 2 phases.

Cela permet de gérer intuitivement dans quels objets de la page l'évènement est supposé se déclencher. Néanmoins il est possible de stopper la propagation de l'évènement en JavaScript afin de le traiter différemment.

Gestion des évènements : Exemple de propagation

Evénement clic sur un lien <a href="nextpage.html">

document.getElementsByTagName("a")[0].onclick = function(e){
    alert('clic sur lien');
    e.preventDefault();
};

document.body.onclick = function(e){
    alert('clic sur page');
}; 

'clic sur lien' sera affiché avant 'clic sur page', et e.preventDefault() empêche l'utilisateur de changer de page au clic sur le lien.

Gestion des évènements : Ajout de listeners

On a vu qu'on pouvait écouter des évènements via les event attributes (DOMElement.onEvenement ou <tag onEvenement="doSomething();">).

On peut aussi gérer plus précisément en Javascript les listeners d'un objet:

Un mot sur les moteurs d'exécution JavaScript

Les moteurs JavaScript ont pour rôle d'intrepréter et d'éxécuter le code Javascript au sein du navigateur. Ils se sont grandement améliorés récemment grâce à la concurrence.

Avec des mécanismes de compilation à la volée et une amélioration du garbage collector, les éditeurs de navigateurs sont en pleine compétition pour la performance de leurs moteurs d'exécution JavaScript.

Liste des moteurs principaux :

Usages modernes

le JavaScript passe à la seconde vitesse

Les nouveautés issues de la tambouille HTML5

Toutes ces nouvelles fonctions se présentent sous la forme d'API Javascript.

Web Mobile

Profiter de la mobilité pour de nouvelles interactions

De nouvelles API JavaScript sont là, mais les vieux mobiles ne sont pas compatibles. Aucun souci pour les smartphones récents.

WebSockets

Le protocole WebSocket permet de créer un canal de communication bidirectionnel entre un serveur web et un navigateur. Ce canal est basé sur une socket TCP.

Les échanges de données sont de plus petite taille et plus rapides qu'en utilisant AJAX et l'objet XMLHTTPRequest

Les WebSockets seront utiles pour toutes les applications nécessitant des échanges rapides et réguliers entre serveur et client : informations en direct, suivi de cours boursiers, chat en ligne, jeux multijoueurs...

WebSockets : Utilisation en Javascript

//Création du canal
var ws= new WebSocket("ws://websocketUrl");

ws.onopen = function(evt) { alert("Connection open ..."); }; 
ws.onmessage = function(evt) { alert( "Received Message: " + evt.data); }; 
ws.onclose = function(evt) { alert("Connection closed."); };
ws.onerror = function(err) { alert("WebSocket error : " + err.data) };

//Pour envoyer des messages ou données on utilise la fonction send :
ws.send(MyMessage);

ws.close();	

WebSockets : Exemple d'implémentation serveur avec Glassfish

public class WebSocketServlet extends HttpServlet {
	private final SuperApplication app = new SuperApplication();
	public void init(ServletConfig config) throws ServletException {
 		   WebSocketEngine.getEngine().register(app);
 	 }
 }
 public class SuperApplication extends WebSocketApplication {
	public WebSocket createSocket(WebSocketListener... listeners) throws IOException {
		return new BaseServerWebSocket(listeners);
	}

        public void onMessage(WebSocket socket, DataFrame frame) throws IOException {
		final String data = frame.getTextPayload(); //on a récupéré les données
	}
	//BaseWebServerSocket délègue onOpen, onClose 
	//et onMessage à WebSocketApplication
}	

<canvas> , le tueur de Flash ?

Pourquoi <canvas> prend du terrain à Flash ?

WebGL

Le Web passe aussi en 3D

Du JavaScript côté serveur aussi

node.js est un framework Javascript serveur construit au dessus de V8, le très performant moteur Javascript open source utilisé par Chrome.

Il est un sérieux concurrent à Apache car permet d'utiliser des IO non bloquantes pour gérer toutes les requêtes entrantes, sortantes ainsi que tout le process lié à la requête. Toutes les fonctions de node.js sont asynchrones, ainsi le développeur n'a plus à gérer la concurrence au sein de son application.

Ainsi il excelle dans le domaine des applications web temps réel ou asynchrones. De plus, il est basé sur la programmation évènementielle et le JavaScript est le langage idéal pour cela.

Le JavaScript pourrait-il sortir du navigateur ?

Un certain nombre de développeurs aimeraient que les spécifications du Javascript aillent un peu plus que loin que les applications basées sur un navigateur.

Le projet CommonJS vise à concevoir une API standard permettant d'écrire des applications côté serveur, des outils en ligne de commande ou encore des applications GUI desktop.

Le groupe espère parvenir à une librairie aussi riche que ce qu'offre aujourd'hui Ruby, Python et Java.

Pourquoi apprendre le JavaScript maintenant ?