5. Introduction / But de la présentation
Redécouvrir un langage pour
en faire un meilleur usage
6. Introduction / Plan de la présentation
1. Introduction / Rappels
2. Les fonctions / Les objets
3. Les closures
4. Le pattern IIFE
5. Le prototype
6. Exposition de ces principes dans le code
source de jQuery / dans un plugin
7. Introduction / Plan de la présentation
1. Introduction / Rappels
2. Les fonctions / Les objets
3. Les closures
4. Le pattern IIFE
5. Le prototype
6. Exposition de ces principes dans le code source de jQuery / dans un plugin
Fonction
Objet
Scope
Closure Prototype
8. Rappels
En Javascript, tout est Objet.
false.toString();//false
[1,2,3].toString();//"1,2,3“
function maFonction(){}
maFonction.toto = "test";
maFonction.toto;//"test"
9. Rappels
Les objets en tant que
conteneurs de données
var personne = {
nom:'ROSSET',
prenom:'Christophe'
}
10. Functions / Déclaration
Plusieurs façons de déclarer
une fonction
•function declaration
•function expression
//function declaration
function maFonction(){}
//function expression
var autreFonction = function(){};
11. Functions / Scopes
Scope = portée des variables
Une variable est globale ou limitée au scope
d’une fonction
12. Functions / Scopes / Mot clé var
N’oubliez pas le mot clé var
devant le nom de vos variables !
13. Functions / Scopes / Mot clé var
Portée des variables en fonction du mot clé var
•Une variable déclarée sans le mot clé var est automatiquement globale.
•Une variable déclarée avec le mot clé var, hors d'une fonction est globale.
•Une variable déclarée sans le mot clé var, dans une fonction est globale.
•Une variable déclarée avec le mot clé var, dans une fonction est locale à cette
fonction.
14. Functions / Scopes / Mot clé var
N’oubliez pas le mot clé var
devant le nom de vos variables !
//même effet, mais prenez l'habitude d'utiliser le mot clé var.
var toto = "Je suis déclaré dans le scope global";
toto = "Je suis aussi déclaré dans le scope global";
function test(){
var toto = "Je n'existe que dans le scope de la fonction test()";
}
15. Functions / Scopes / Mot clé var
N’oubliez pas le mot clé var
devant le nom de vos variables !
var toto = "Je suis une globale";
function test(){
toto = "Tiens j'ai oublié le mot clé var ...";
}
console.log(toto);//"Je suis une globale"
test();
console.log(toto);//"Tiens j'ai oublié le mot clé var ..."
16. Functions / Scopes / Objet window
L’objet window est créé par le navigateur lors
de l’ouverture d’une page
//ces trois déclarations sont équivalentes
toto = "Je suis une globale";
var toto = "Je suis une globale";
window.toto = "Je suis une globale";
17. Functions / Constructeur
En javascript : pas d’objets instanciés à partir d’une Classe.
Les fonctions font office de constructeur avec le mot clé new.
//Php : différence entre Class, //Javascript
function et instance function maClasse(){
this.methode = function(){}
Class maClasse { }
public function methode(){} var instance = new maClasse();//objet
} maClasse();//appel de la fonction
$instance = new maClasse();
18. Functions / Différence entre une instance et une
« classe » instanciable (une fonction)
var instance = {
methode:function(){}
}
instance.methode();//appel la methode déclaré sur cet objet
var instance = new instance();//TypeError: object is not a function
/** ------------------ */
function maClasse(){
this.methode = function(){}
}
var instance = new maClasse();
instance.methode();//appel la méthode déclaré sur l'objet instancié
maClasse.methode();//TypeError: Object function maClasse() has no method 'methode‘
/** ------------------ */
var objetVide = {};
20. Functions / this
Appelé comme un objet ou une fonction, this sera toujours présent
function maFonction(){
console.log(this);
}
maFonction();//appelé de cette façon, this fera référence à la variable global window
/** ------------------ */
function maClasse(){
this.methode = function(){
console.log(this);
}
}
var instance = new maClasse();
instance.methode();//appelé de cette façon, this fera référence à mon objet instance
21. Functions / this / Function expression
Appelé comme un objet ou une fonction, this sera toujours présent
jQuery('body').click(function(){
jQuery(this).addClass('tata');
})
//equivaut à
jQuery('body').click(maFonction);
function maFonction(){
jQuery(this).addClass('tata');
}
22. Functions / call - apply
En utilisant call ou apply, la valeur de this à l'intérieur de la fonction
appelée est settée avec celle du première argument
function ttc(net,taxes){
console.log(net+taxes);
}
ttc(100,20);//affiche 120
var objetVide = {};
ttc.call(objetVide,100,20);//affiche 120
ttc.apply(objetVide,[100,20]);//affiche 120
23. Functions / call – apply / exemple
var prime = {
id:123456,
payeur:"MESSALI",
// ...
net:200,
taxes:20
}
var devis = {
id:456879,
idClient:46846,
// ...
net:1500,
taxes:250
}
function getTtc(){
var ttc = this.net + this.taxes;
console.log(ttc);
}
var ttcPrime = getTtc.call(prime);//affiche 220
var ttcDevis = getTtc.call(devis);//affiche 1750
24. Functions / arguments
Comme il existe par défaut une variable this dans toute fonction, il
existe une variable arguments qui est un tableaux des arguments
passés à la fonction.
function ttc(net,taxes){
console.log(net+taxes);
}
function aliasTtc(){
ttc.apply({},arguments);
}
ttc(100,20);//affiche 120
aliasTtc(100,20);//affiche 120
/** ------------------ */
//nombre d'arguments variables
function message(){
var message = "";
for(var i = 0; i < arguments.length; i++){
message += arguments[i]+' ';
}
console.log(message);
}
message('Bonjour','je','suis','Tophe');
message('Hello','world');
25. Functions / Closures
En Javascript : pas de variable privée/publique,
uniquement le scope de la fonction.
Le scope de cette fonction conserve l'accès au
scope au dessus de lui lorsqu'il a été défini.
26. Functions / Closures
Exemple de variable privée
function Counter(start) {
//variable définie dans le scope Counter
var count = start;
//méthode définie dans le scope Counter -> a accès à la variable count
this.increment = function() {
count++;
}
//méthode définie dans le scope Counter -> a accès à la variable count
this.get = function() {
return count;
}
}
var toto = new Counter(10);
toto.increment();
toto.get();//11
/** ------------------ */
toto.hack = function(){
count = 23;
}
toto.get();//11
27. Functions / Pattern IIFE
IIFE = Immediatly Invoked Function Expression
parfois nommé
Anonymous Wrappers
ou
Self-Invoked Anonymous Function
(function(){
//code
})()
28. Functions / Pattern IIFE
IIFE = Immediatly Invoked Function Expression
parfois nommé
Anonymous Wrappers
ou
Self-Invoked Anonymous Function
( //evalue la fonction à l'intérieur des parenthèses
function(){}
) //retourne l'objet fonction
() //appelle le resultat
/** ------------------ */
(function(arg){
console.log(arg);//affiche "toto"
})('toto')
29. Functions / Pattern IIFE / Namespace protégé
(function(window){
//"namespace" protégé
function transform(str){
return str.toUpperCase();
}
function Client(nom,prenom){
this.nom = transform(nom);
this.prenom = transform(prenom);
this.display = function(){
console.log(this.prenom+' '+this.nom);
}
}
//seul l'objet Client sera visible dans le scope global
window.Client = Client;
})(window)
//scope global
var instance = new Client('Rosset','Christophe');
instance.display();//CHRISTOPHE ROSSET
transform('toto');//ReferenceError: transform is not defined
30.
31. Functions / Prototype
•Chaque objet descend de Object
•Chaque objet contient un attribut "prototype"
•Il est possible d'ajouter des attributs/fonctions à
ce prototype de façon à enrichir l'objet concerné
32. Functions / Prototype / Ajout de méthode
Ajout de méthode à un objet sans l’étendre
function Animal(){
this.type = "Un animal";
this.mange = function(){console.log(this.type+' ça mange');}
}
Animal.prototype.dors = function(){console.log(this.type+' ça dors');}
var c = new Animal();
c.mange();//Un animal ça mange
c.dors();//Un animal ça dors
33. Functions / Prototype / Chaîne Prototype
Pour récupérer une propriété, javascript remonte
la chaine de prototype jusqu’à la trouver
34. Functions / Prototype / Chaîne Prototype
function Animal(){
this.type = "Un animal";
this.mange = function(){console.log(this.type+' ça mange');}
}
function Chat(){
this.type = "Un chat";
this.miaule = function(){console.log(this.type+' ça miaule');}
}
function Chaton(){
this.type = "Un chaton";
this.joue = function(){console.log(this.type+' ça joue');}
}
//assigner au prototype de Chat une instance de Animal
Chat.prototype = new Animal;
//assigner au prototype de Chaton une instance de Chat
Chaton.prototype = new Chat;
var a = new Chaton();
a.joue();//Un chaton ça joue /** la chaine prototype
a.miaule();//Un chaton ça miaule a [instanceof Chaton]
a.mange();//Un chaton ça mange joue [function]
type "Un chaton"
var b = new Chat(); __proto__ [instanceof Chat]
b.miaule();//Un chat ça miaule miaule [function]
b.mange();//Un chat ça mange type "Un chat"
__proto__ [instanceof Animal]
var c = new Animal(); mange [function]
c.mange();//Un animal ça mange type "Un animal"
__proto__ [instanceof Object]
...
35. Functions / Prototype / Objets natifs
Modification du prototype des objets natifs : déconseillé. A part pour
porter une méthode apparue dans une nouvelle version de Javascript
sur un ancien navigateur tel que IE6
if (!Array.prototype.forEach)
{
Array.prototype.forEach = function(fun /*, thisp*/)
{
var len = this.length;
if (typeof fun != "function")
throw new TypeError();
var thisp = arguments[1];
for (var i = 0; i < len; i++)
{
if (i in this)
fun.call(thisp, this[i], i, this);
}
};
}
['tata','titi','toto'].forEach(function(value,index){
console.log(index+' '+value);
})
//0 tata 1 titi 2 toto
36. Functions / Prototype / Objets natifs
Quelques exemples avec des objet natifs
Object.prototype.test = "toto";
var objetTest = {a:'toto'}
var stringTest = "azertyuiop";
var arrayTest = [1,2,3,4];
console.log(objetTest.test);//toto
console.log(stringTest.test);//toto
console.log(arrayTest.test);//toto
/** ------------------ */
Number.prototype.toEuros = function(){
return (Math.round(this*100)/100).toString().replace('.',',')+'€';
}
125.12254.toEuros();//"125,12€"
37. Functions / Prototype / hasOwnProperty
La seule façon de savoir si une propriété est définie sur l'objet lui même et
non quelque part dans sa chaine prototype est d'utiliser .hasOwnProperty
//modification du prototype de Object
Object.prototype.toto = 'Hello world';
var obj = {societe:'Neuros'};
obj.societe;//"Neuros"
obj.toto;//"Hello world"
'societe' in obj;//true
'toto' in obj;//true
obj.hasOwnProperty('societe');//true
obj.hasOwnProperty('toto');//false
38. Functions / Prototype / hasOwnProperty / boucle for in
//modification du prototype de Object
Object.prototype.toto = 'Hello world';
var obj = {societe:'Neuros'};
//log : societe toto
for(var i in obj){
console.log(i);
}
//log : societe
for(var i in obj){
if(obj.hasOwnProperty(i)){
console.log(i);
}
}
39. Functions / Prototype / Closures - Encapsulation
•Les méthodes définies à l'intérieur du constructeur (Counter) ont accès à la variable count.
•Les méthodes définies sur le prototype ne sont pas définies sur le scope du constructeur et n'ont
pas accès aux variables locales du constructeur.
function Counter(start) {
//variable définie dans le scope Counter
var count = start;
//méthode définie dans le scope Counter -> a accès à la variable count
this.increment = function() {
count++;
}
//méthode définie dans le scope Counter -> a accès à la variable count
this.get = function() {
return count;
}
}
//methode set créé une nouvelle closure n'ayant pas accès à count
Counter.prototype.set = function(value){
//count est global
//si on met var count, on fait une variable locale à set
count = value;
}
var toto = new Counter(10);
toto.increment();
toto.get();//11
toto.set(200);
toto.get();//11
43. Ressources :
jQuery
http://paulirish.com/2010/10-things-i-learned-from-the-jquery-source/
Javascript Objet
http://mckoss.com/jscript/object.htm
http://blog.mklog.fr/article/js-oo-et-manipulation-prototype-via-call-apply
Javascript en général
http://bonsaiden.github.com/JavaScript-Garden/
Javascript is not only jQuery (si vous n’êtes pas convaincu)
http://www.slideshare.net/rmurphey/the-jquery-divide-5287573