JavaScript
Bases du langage et son évolution
Minh hai Nguyen, Sylvain Pollet-Villard
7 novembre 2011
Minh hai Nguyen, Sylvain Pollet-Villard
7 novembre 2011
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.
<script src="js/monscript.js"></script>
<script type='text/javascript'> // Code JavaScript </script>
<li onclick="this.style.backgroundColor = 'orange';"> ... </li>
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
var company = { name: "Ninjavascript", boss: { name : "Bill", salary : 8000 }, makeAdvertisement:function(){ alert('Ninjavascript rocks !'); } }; company.makeAdvertisement(); company.boss.name; company["boss"]["salary"];
// 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
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 !
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;
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;
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;
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;
<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>
document est un objet du scope global dans toute page Web
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);
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.
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.
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:
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 :
le JavaScript passe à la seconde vitesse
Toutes ces nouvelles fonctions se présentent sous la forme d'API Javascript.
Profiter de la mobilité pour de nouvelles interactions
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...
//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();
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 }
Le Web passe aussi en 3D
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.
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.