Javascript


Les fondamentaux
      La POO



               Jean-pierre VINCENT
Qui ça ?
       Jean-pierre VINCENT

braincracking.org (veille techno)
@theystolemynick

10 ans de Web
Consultant, formateur, expertise
Pourquoi Javascript ?
Présent partout
● Navigateur
● Jeux Web (remplace Flash)

● Mobile (Phonegap ...)

● Télévisions

● Serveur (Node.js, ...)

● Software (Chromeless, ...)

● OS (JoliCloud, WebOS...)

● Windows 8 !
Mauvaise réputation
Mauvaise réputation

parseInt('06'); // 6
parseInt('08'); // 0




           wftjs.com
Mauvaise réputation

typeof NaN // number
NaN === NaN // false

typeof null // object
null instanceof Object // false



            wftjs.com
Mauvaise réputation

(1.7976931348623157e+308 ===
 1.7976931348623158e+308 )// true!

 alert(111111111111111111111); //
alerts 111111111111111110000

9999999999999999 //=> 10000000000000000
APIs
●   DOM

●   Node

●   WinRT

...
●
Compliqué ?
Différent !
Historique court
● Né pendant la guerre (95)
● En quelques semaines

● Influence Java, Erlang, Lisp, Python




     IE et Netscape d'accord pour
             EcmaScript 3
Evolution
● EcmaScript 5
● Harmony

● EcmaScript.Next

● EcmaScript.Next.Next
En attendant ...


   EcmaScript 3
Objectif de cette heure

● Savoir deboguer avec 3
fondamentaux


●   Développer Orienté Objet
Notions de base
●   Portée des variables (var + function)

●   Function()

●   Contexte (this)
Portée des variables

         1 closure = 1 portée

Closure = function() {
  PORTÉE
}
Portée des variables
test1 = function() {
  var x = 1;
  test2 = function() {
    var x = 2;
    test3 = function() {
      var x = 3;
     console.log(x); // 3
    }();
  }();
  console.log(x); // 1
}();
console.log(x); // undefined
Boucle infinie !
function genericFunctionName() {
  for(i = 0; i < myArray.length; i++) {
    ....
  }
}

for(i = 0; i < 10; i++) {
  genericFunctionName();
}
Boucle corrigée
function genericFunctionName() {
  for( var i = 0; i<myArray.length;i++){
    ....
  }
}

for(i = 0; i < 10; i++) {
  genericFunctionName();
}
Application pratique
(function() {
  var privateVariable = true;
  function init() {
     console.log( privateVariable );
  }
}())

init(); // true
console.log(privateVariable);//undefined
Créer un scope
1

 function() {
    var privateVariable = true;
    console.log( privateVariable );
 }
 => parse error
Créer un scope
2

( function() {
    var privateVariable = true;
    console.log( privateVariable );
 })
 => rien
Créer un scope
3

( function() {
    var privateVariable = true;
    console.log( privateVariable );
 })()
 => true
Notions de base
✓ Portée des variables (var + function)

●   Function()

●   Contexte (this)
Function()
●   function action() {}


●   action = function() {}


●   action();
function action()

Toujours globale

action(); // true
..
function action() {
  console.log(true);
}
function action()
TROP globale
action(); // a !== 1
if( a === 1) {
  function action() {
    console.log('a === 1');
  }
} else {
  function action() {
     console.log('a !== 1');
  }
}
var action = function()


  Permet de choisir la portée
Peut s'auto-exécuter
autoInit = function() {
    console.log('hello world');
}();
// hello world
return function()
var onDOMEvent =
 function( el, ev, callback) {
  if(document.body.attachEvent){
         el.attachEvent('on'+ev, callback);
  } else {
         el.addEventListener( ev, callback);
     }
};
return function()
var onDOMEvent =
function( el, ev, callback) {
  if(document.body.attachEvent
    return function(el, ev, callback) {
element.attachEvent('on'+event, callback);
   };
  else
       return function(el, ev, callback) {
       el.addEventListener( ev, callback);
       };
}();
Function.prototype
 var myClass = function () {
   this.publicVariable = 0;
};

 myClass.prototype = {
   decrement:function() {
      console.log( --this.publicVariable );
   },
   increment:function() {
      console.log( ++this.publicVariable );
   }
};
Function.prototype
 var myClass = function () {};
 myClass.prototype = {
   decrement:function() {},
   increment:function() {}
};
myObject = new myClass();
myObject.decrement(); // -1
myObject.decrement(); // -2
myObject2 = new myClass();
myObject2.increment(); // 1
myObject2.increment(); // 2
Héritage
mySubClass = function() {
    this.publicVariable = 10;
};
mySubClass.prototype = myClass.prototype;
 mySubClass.prototype.constructor =
mySubClass;

myObject2 = new mySubClass();
myObject2.increment(); // 11
myObject2.increment(); // 12
Renvoi d'objets
myClass = function () {
   var privateVariable = 0;
   // public methods
   return {
     decrement:function() {
       console.log( --privateVariable );
     },
     increment:function() {
       console.log( ++privateVariable );
     }
   }
};
Renvoi d'objets
 myClass = function () {
    return {
      decrement:function() {   },
      increment:function() {   }
    }
 };
myObject = myClass();
myObject.decrement(); // -1
myObject.decrement(); // -2
myObject2 = myClass();
myObject2.increment(); // 1
myObject2.increment(); // 2
Function === Object
myClass = function () {
   return {
     publicMethod:function() {}
   }
};
myClass.staticMethod = function() {};

myObject = myClass();
myObject.staticMethod(); // Error

myClass.publicMethod(); // Error
Portée + déclaration
var queries = [ new XHR('url1'), new
XHR('url2'), new XHR('url3')];

for(var i = 0; i < queries.length; i++) {
  queries[i].onload = function() {
     console.log( i ); // référence
  };
}

queries[ 0 ].onload(); // 3!
queries[ 1 ].onload(); // 3!
queries[ 2 ].onload(); // 3!
Portée + déclaration
for(var i = 0; i < queries.length; i++) {
  queries[i].onload = function(i) {
      return function() {
          console.log( i ); // valeur
      };
  }(i); // exécution immédiate
}
// plus tard ...
queries[ 0 ].onload(); // 0
queries[ 1 ].onload(); // 1
queries[ 2 ].onload(); // 2
Notions de base
✓ Portée des variables (var + function)

✓ Function()

●   Contexte (this)
Contexte


this = contexte d'exécution
Contexte - facile
myClass = function() {
     this.id = 'myClass';
}
myClass.prototype = {
     action:function() {
          console.log(this.id);
     }
};

myObject = new myClass();
myObject.action(); // 'myclass'
Contexte - DOM
myClass = function() {
   this.id = 'myClass';
}
myClass.prototype = {
   action:function() {
   console.log(this.id);
   }
};
myObject = new myClass();
document.body.onclick = myObject.action;

// document.body.id
Contexte – tous objets
myClass = function() {
   this.id = 'myClass';
}
myClass.prototype = {
   action:function() {
   console.log(this.id);
   }
};
myObject = new myClass();
myEvent = {
     id:'myObj2'
}
myEvent.onfire = myObj.action;
myEvent.onfire(); // myObj2
Contexte – fix natif
myClass = function() {
   this.id = 'myClass';
}
myClass.prototype = {
   action:function() {
   console.log(this.id);
   }
};
myObject = new myClass();
myEvent = {
     id:'myObj2'
}
myEvent.onfire = myObj.action;
myEvent.onfire.call( myObject ); // myClass
Contexte: sans prototype
myClass = function() {
   this.id = 'myClass';
   var me = this;
   return {
     action:function() {
       console.log(me.id);
     }
   }
};
 myObject = myClass();
 document.body.onclick = myObject.action;
 // 'myClass'
Notions de base
✓ Portée des variables (var + function)

✓ Function()

✓ Contexte (this)
Développement durable

●   Pollution du scope global


●   Programmation Orienté Objet
Pollution globale
Pollution globale
    2 exemples complètement au hasard
●Gmail : 33 variables globales (450K lignes
de code)


●   Lemonde.fr : 480 variables globales
Actions
✗ Function action() {}

✓ var action = function() {
      var myVariable;
  }

✓namespaces
Namespaces
var MY_APP_NAMESPACE = {};

MY.doSomething = function() {};

MY.utils = {};

MY.utils.XHR = function() {

}
Namespaces - astuce
récupérer ou créer un namespace
MY = windows.MY || {};

MY.utils = MY.utils || {};
Création d'un scope
Rappel

(function(){ // début de scope local
    var private = true;

// ici je suis chez moi

})(); // fin de scope local
Programmation
Orienté
Objet
Tout est objet
"abc".indexOf('a');

[1,2,3].slice(1);

13.3714 .toFixed(1);

/[0-9]/g.test('10/11/2011');
POO Classique
 new, class, static,
public, private,
__construct, $this, const,
self::, extends, protected,
parent::, abstract, final,
interface, implements,
instanceof
POO JS

new (optionel)
this (particulier)
instanceof
Interface publique
(function(){ // début de scope local

 // accès global au constructeur
 MY.utils.XHR = function( url ) {
    this.url = url;
 };
 // méthodes ou variable statiques
 MY.utils.XHR.staticVariable = true;

})(); // fin de scope local
Raccourci
(function(){ // début de scope local

 // raccourci vers le namespace
utilisé
   var self = MY.utils.XHR;

  self.staticVariable = true;



})(); // fin de scope local
privées communes
(function(){ // début de scope local

// accès global au constructeur
MY.utils.XHR = function( url ) {
   this.url = url;
   currentInstances.push( this );
};
var currentInstances = [];


})(); // fin de scope local
privées par instance
(function(){ // début de scope local
// accès global au constructeur
MY.utils.XHR = function( url ) {
   var isConnecting = true;
   return {
     query:function() {
       if( isConnecting)
         return false;
     }
   }
};
})(); // fin de scope local
Combo : factory pattern
(function(){
MY.utils.XHR = function( ) {
   throw new Error( 'please use .getInstance()' );
};
// constructeur privé
var XHR = function(url) { console.log(url); };
// liste privée
var currentInstances = {};
// factory
MY.utils.XHR.getInstance = function( url ) {
   if(currentInstances[url])
     return currentInstances[url];
   else
     return currentInstances[url] = new XHR( url);
}
})();
Tout est émulable
●   programmation événementielle

●   tests unitaires et fonctionnels

● patterns classiques : MVC, observer,
facade, proxy, singleton, factory ...
Conclusion

●   Javascript est différent, apprenez le

●   OOP réutilisable
Questions ?


Jean-pierre VINCENT
braincracking.org
@theystolemynick

Javascript : fondamentaux et OOP

  • 1.
    Javascript Les fondamentaux La POO Jean-pierre VINCENT
  • 2.
    Qui ça ? Jean-pierre VINCENT braincracking.org (veille techno) @theystolemynick 10 ans de Web Consultant, formateur, expertise
  • 4.
  • 5.
    Présent partout ● Navigateur ●Jeux Web (remplace Flash) ● Mobile (Phonegap ...) ● Télévisions ● Serveur (Node.js, ...) ● Software (Chromeless, ...) ● OS (JoliCloud, WebOS...) ● Windows 8 !
  • 6.
  • 7.
    Mauvaise réputation parseInt('06'); //6 parseInt('08'); // 0 wftjs.com
  • 8.
    Mauvaise réputation typeof NaN// number NaN === NaN // false typeof null // object null instanceof Object // false wftjs.com
  • 9.
    Mauvaise réputation (1.7976931348623157e+308 === 1.7976931348623158e+308 )// true! alert(111111111111111111111); // alerts 111111111111111110000 9999999999999999 //=> 10000000000000000
  • 10.
    APIs ● DOM ● Node ● WinRT ... ●
  • 11.
  • 12.
  • 13.
    Historique court ● Népendant la guerre (95) ● En quelques semaines ● Influence Java, Erlang, Lisp, Python IE et Netscape d'accord pour EcmaScript 3
  • 14.
    Evolution ● EcmaScript 5 ●Harmony ● EcmaScript.Next ● EcmaScript.Next.Next
  • 15.
    En attendant ... EcmaScript 3
  • 16.
    Objectif de cetteheure ● Savoir deboguer avec 3 fondamentaux ● Développer Orienté Objet
  • 17.
    Notions de base ● Portée des variables (var + function) ● Function() ● Contexte (this)
  • 18.
    Portée des variables 1 closure = 1 portée Closure = function() { PORTÉE }
  • 19.
    Portée des variables test1= function() { var x = 1; test2 = function() { var x = 2; test3 = function() { var x = 3; console.log(x); // 3 }(); }(); console.log(x); // 1 }(); console.log(x); // undefined
  • 20.
    Boucle infinie ! functiongenericFunctionName() { for(i = 0; i < myArray.length; i++) { .... } } for(i = 0; i < 10; i++) { genericFunctionName(); }
  • 21.
    Boucle corrigée function genericFunctionName(){ for( var i = 0; i<myArray.length;i++){ .... } } for(i = 0; i < 10; i++) { genericFunctionName(); }
  • 22.
    Application pratique (function() { var privateVariable = true; function init() { console.log( privateVariable ); } }()) init(); // true console.log(privateVariable);//undefined
  • 23.
    Créer un scope 1 function() { var privateVariable = true; console.log( privateVariable ); } => parse error
  • 24.
    Créer un scope 2 (function() { var privateVariable = true; console.log( privateVariable ); }) => rien
  • 25.
    Créer un scope 3 (function() { var privateVariable = true; console.log( privateVariable ); })() => true
  • 26.
    Notions de base ✓Portée des variables (var + function) ● Function() ● Contexte (this)
  • 27.
    Function() ● function action() {} ● action = function() {} ● action();
  • 28.
    function action() Toujours globale action();// true .. function action() { console.log(true); }
  • 29.
    function action() TROP globale action();// a !== 1 if( a === 1) { function action() { console.log('a === 1'); } } else { function action() { console.log('a !== 1'); } }
  • 30.
    var action =function() Permet de choisir la portée
  • 31.
    Peut s'auto-exécuter autoInit =function() { console.log('hello world'); }(); // hello world
  • 32.
    return function() var onDOMEvent= function( el, ev, callback) { if(document.body.attachEvent){ el.attachEvent('on'+ev, callback); } else { el.addEventListener( ev, callback); } };
  • 33.
    return function() var onDOMEvent= function( el, ev, callback) { if(document.body.attachEvent return function(el, ev, callback) { element.attachEvent('on'+event, callback); }; else return function(el, ev, callback) { el.addEventListener( ev, callback); }; }();
  • 34.
    Function.prototype var myClass= function () { this.publicVariable = 0; }; myClass.prototype = { decrement:function() { console.log( --this.publicVariable ); }, increment:function() { console.log( ++this.publicVariable ); } };
  • 35.
    Function.prototype var myClass= function () {}; myClass.prototype = { decrement:function() {}, increment:function() {} }; myObject = new myClass(); myObject.decrement(); // -1 myObject.decrement(); // -2 myObject2 = new myClass(); myObject2.increment(); // 1 myObject2.increment(); // 2
  • 36.
    Héritage mySubClass = function(){ this.publicVariable = 10; }; mySubClass.prototype = myClass.prototype; mySubClass.prototype.constructor = mySubClass; myObject2 = new mySubClass(); myObject2.increment(); // 11 myObject2.increment(); // 12
  • 37.
    Renvoi d'objets myClass =function () { var privateVariable = 0; // public methods return { decrement:function() { console.log( --privateVariable ); }, increment:function() { console.log( ++privateVariable ); } } };
  • 38.
    Renvoi d'objets myClass= function () { return { decrement:function() { }, increment:function() { } } }; myObject = myClass(); myObject.decrement(); // -1 myObject.decrement(); // -2 myObject2 = myClass(); myObject2.increment(); // 1 myObject2.increment(); // 2
  • 39.
    Function === Object myClass= function () { return { publicMethod:function() {} } }; myClass.staticMethod = function() {}; myObject = myClass(); myObject.staticMethod(); // Error myClass.publicMethod(); // Error
  • 40.
    Portée + déclaration varqueries = [ new XHR('url1'), new XHR('url2'), new XHR('url3')]; for(var i = 0; i < queries.length; i++) { queries[i].onload = function() { console.log( i ); // référence }; } queries[ 0 ].onload(); // 3! queries[ 1 ].onload(); // 3! queries[ 2 ].onload(); // 3!
  • 41.
    Portée + déclaration for(vari = 0; i < queries.length; i++) { queries[i].onload = function(i) { return function() { console.log( i ); // valeur }; }(i); // exécution immédiate } // plus tard ... queries[ 0 ].onload(); // 0 queries[ 1 ].onload(); // 1 queries[ 2 ].onload(); // 2
  • 42.
    Notions de base ✓Portée des variables (var + function) ✓ Function() ● Contexte (this)
  • 43.
  • 44.
    Contexte - facile myClass= function() { this.id = 'myClass'; } myClass.prototype = { action:function() { console.log(this.id); } }; myObject = new myClass(); myObject.action(); // 'myclass'
  • 45.
    Contexte - DOM myClass= function() { this.id = 'myClass'; } myClass.prototype = { action:function() { console.log(this.id); } }; myObject = new myClass(); document.body.onclick = myObject.action; // document.body.id
  • 46.
    Contexte – tousobjets myClass = function() { this.id = 'myClass'; } myClass.prototype = { action:function() { console.log(this.id); } }; myObject = new myClass(); myEvent = { id:'myObj2' } myEvent.onfire = myObj.action; myEvent.onfire(); // myObj2
  • 47.
    Contexte – fixnatif myClass = function() { this.id = 'myClass'; } myClass.prototype = { action:function() { console.log(this.id); } }; myObject = new myClass(); myEvent = { id:'myObj2' } myEvent.onfire = myObj.action; myEvent.onfire.call( myObject ); // myClass
  • 48.
    Contexte: sans prototype myClass= function() { this.id = 'myClass'; var me = this; return { action:function() { console.log(me.id); } } }; myObject = myClass(); document.body.onclick = myObject.action; // 'myClass'
  • 49.
    Notions de base ✓Portée des variables (var + function) ✓ Function() ✓ Contexte (this)
  • 50.
    Développement durable ● Pollution du scope global ● Programmation Orienté Objet
  • 51.
  • 52.
    Pollution globale 2 exemples complètement au hasard ●Gmail : 33 variables globales (450K lignes de code) ● Lemonde.fr : 480 variables globales
  • 53.
    Actions ✗ Function action(){} ✓ var action = function() { var myVariable; } ✓namespaces
  • 54.
    Namespaces var MY_APP_NAMESPACE ={}; MY.doSomething = function() {}; MY.utils = {}; MY.utils.XHR = function() { }
  • 55.
    Namespaces - astuce récupérerou créer un namespace MY = windows.MY || {}; MY.utils = MY.utils || {};
  • 56.
    Création d'un scope Rappel (function(){// début de scope local var private = true; // ici je suis chez moi })(); // fin de scope local
  • 57.
  • 58.
    Tout est objet "abc".indexOf('a'); [1,2,3].slice(1); 13.3714.toFixed(1); /[0-9]/g.test('10/11/2011');
  • 59.
    POO Classique new,class, static, public, private, __construct, $this, const, self::, extends, protected, parent::, abstract, final, interface, implements, instanceof
  • 60.
    POO JS new (optionel) this(particulier) instanceof
  • 61.
    Interface publique (function(){ //début de scope local // accès global au constructeur MY.utils.XHR = function( url ) { this.url = url; }; // méthodes ou variable statiques MY.utils.XHR.staticVariable = true; })(); // fin de scope local
  • 62.
    Raccourci (function(){ // débutde scope local // raccourci vers le namespace utilisé var self = MY.utils.XHR; self.staticVariable = true; })(); // fin de scope local
  • 63.
    privées communes (function(){ //début de scope local // accès global au constructeur MY.utils.XHR = function( url ) { this.url = url; currentInstances.push( this ); }; var currentInstances = []; })(); // fin de scope local
  • 64.
    privées par instance (function(){// début de scope local // accès global au constructeur MY.utils.XHR = function( url ) { var isConnecting = true; return { query:function() { if( isConnecting) return false; } } }; })(); // fin de scope local
  • 65.
    Combo : factorypattern (function(){ MY.utils.XHR = function( ) { throw new Error( 'please use .getInstance()' ); }; // constructeur privé var XHR = function(url) { console.log(url); }; // liste privée var currentInstances = {}; // factory MY.utils.XHR.getInstance = function( url ) { if(currentInstances[url]) return currentInstances[url]; else return currentInstances[url] = new XHR( url); } })();
  • 66.
    Tout est émulable ● programmation événementielle ● tests unitaires et fonctionnels ● patterns classiques : MVC, observer, facade, proxy, singleton, factory ...
  • 67.
    Conclusion ● Javascript est différent, apprenez le ● OOP réutilisable
  • 68.