mardi 26 octobre 2010
Nous voilà enfin au dernier piège de cette série de 5 astuces JavaScript. Après, je pourrai décortiquer une par une les 14 questions du Quiz que j'ai si bien réussi (3/14).
Dans cet exemple, savez-vous ce qu'affichera alert(this) ?
function a(){Est-ce que this fait référence à la fonction elle-même ? À sa portée locale ? Pourquoi appeler call() sur la fonction a() si on peut tout simplement appeler a() directement ? Pour ma part, j'ignorais la réponse. Mieux valait tester.
alert(this);
}
a.call(null);
Réponse : alert(this) affichera [object Window] dans Firefox (object DOMWindow dans Chrome et object dans IE8).
Celle-là, je n'étais pas certain de la comprendre. Surtout parce que je ne connaissais pas le mécanisme de la fonction call appliqué à une fonction. Regardons de plus près son comportement.
a(); // affiche object WindowAlors c'est quoi le piège ? La fonction a() ne prend pas d'argument en entrée. Par contre, l'appel à call() avec null comme argument laisse sous-entendre qu'on peut lui passer quelque chose. Mais à quoi ça peut servir ?
a.call(); // encore object Window
a.call(null); // toujours object Window
var x = 18;Donc à l'intérieur de la fonction, this prend en référence l'objet qu'on passe en paramètre à call().
a.call(x); // affiche 18
var obj = { label : 'Code 18', value : 18 }
a.call(obj); // affiche object Object
Si j'ai une fonction b(x, y) qui accepte 2 arguments :
function b(x,y){Si on change la fonction b() pour imprimer la valeur de this :
console.log(x);
console.log(y);
}
b(10, 20); // affichera 10 et 20
b.call(10, 20); // affichera 20 et undefined
function b(x,y){En utilisant le mécanisme de call(), le premier paramètre sera la référence à l'objet à utiliser, les suivants seront les arguments de la fonction. Pour obtenir le même résultat, il aurait fallu faire l'appel ainsi :
console.log(this); // 10 {}, un objet sans propriétés ?
console.log(x); // 20
console.log(y); // undefined
}
b(10, 20);Un exemple simple sur la référence :
b.call(null, 10, 20);
var obj = { label : 'Code', value : 18 }À l'intérieur de c(), this n'égalera pas object Window mais bien l'objet obj avec ses propriétés. Si la valeur est omise ou nulle, this sera par défaut le plus proche parent.
c.call(obj, 10, 20, 30);
function c(x, y, z){
console.log(this.label); // Code
console.log(this.value); // 18
console.log(x); // 10
console.log(y); // 20
console.log(z); // 30
}
var z = {Maintenant qu'on comprend l'astuce, je ne veux pas que vous restiez sur votre appétit et je vous suggère une lecture complémentaire qui présente de bons exemples sur l'utilisation de call(). J'ai adapté cet exemple de l'article call and apply que je vous recommande fortement :
x : function(){
console.log(this);
}
}
var obj = { label : 'Code 18', value : 18 };
z.x(); // Object {}, Object étant z
z.x.call(obj); // Object { label="Code 18", more...}
var Character1 = {
name: "Itchy"
}
var Character2 = {
name: "Scratchy"
};
var friendlyGreet = function(somebody) {
console.log("Bonjour " + somebody.name + ", je suis " + this.name);
};
friendlyGreet.call(Character1, Character2); // Bonjour Scratchy, je suis Itchy
friendlyGreet.call(Character2, Character1); // Bonjour Itchy, je suis Scratchy
C'était très intéressant. Par contre, je n'ai pas eu la patience de lire tout l'article sur trephine.org.
J'ai trouvé une explication assez claire ici : http://www.coursweb.ch/javascript/apply-call.html