La chose importante à noter ici est que, puisque Javascript est un langage dynamique , chaque objet n'est, essentiellement, qu'une carte de hachage glorifiée ( à quelques exceptions près ). Et tout dans un objet Javascript est accessible de deux manières - la notation entre crochets et la notation par points.
Je passerai rapidement en revue les deux notations répondant à la première partie de votre question, puis je passerai à la deuxième partie.
Notation entre parenthèses
Ce mode est plus similaire à l'accès aux hashmaps et aux tableaux dans d'autres langages de programmation. Vous pouvez accéder à n'importe quel composant (données (y compris d'autres objets) ou fonction) à l'aide de cette syntaxe.
C'est exactement ce que vous faites dans votre exemple. Vous avez 'a'
, qui est une chaîne (et non un littéral de caractère, comme ce serait le cas dans un langage tel que C ++).
En utilisant la notation des crochets, vous accédez à sa toUpperCase
méthode. Mais y accéder n'est pas encore suffisant; le simple fait de taper alert
, par exemple, en Javascript, n'appelle pas la méthode. C'est juste une simple déclaration. Pour appeler la fonction, vous devez ajouter la parenthèse: alert()
affiche une boîte de dialogue simple contenant undefined
, car elle n'a reçu aucun paramètre. Nous pouvons désormais utiliser ces connaissances pour déchiffrer votre code, qui devient:
alert('a'.toUpperCase());
Ce qui est beaucoup plus lisible.
En fait, un bon moyen de mieux comprendre cela est d'exécuter le Javascript suivant:
alert(alert)
Cela appelle alert
en lui passant un objet fonction, également alert
, sans exécuter également la deuxième alerte. Ce qui s'affiche (au moins dans Chrome 26) est le suivant:
function alert() { [native code] }
Appel:
alert(alert())
affiche deux boîtes de message consécutives contenant undefined
. Ceci est facile à expliquer: l'intérieur alert()
est exécuté en premier, s'affiche undefined
(car il n'a aucun paramètre) et ne renvoie rien. L'alerte externe reçoit la valeur de retour de l'alerte interne - qui n'est rien, et s'affiche également undefined
dans une boîte de message.
Essayez tous les cas sur jsFiddle!
Notation par points
Il s'agit de l'approche plus standard, qui permet d'accéder aux membres d'un objet à l'aide de l' .
opérateur dot ( ). Voici à quoi ressemblerait votre code en notation par points:
alert('a'.toUpperCase())
Beaucoup plus lisible. Alors, quand devrions-nous utiliser la notation par points, et quand devrions-nous utiliser la notation par crochets?
Comparaison
La principale différence entre les deux méthodes est sémantique. Il y a aussi d'autres détails, mais j'y reviendrai dans un instant. Ce qui est le plus important, c'est ce que vous voulez réellement faire - une règle de base est que vous utilisez la notation par points pour les champs et les méthodes bien établis d'un objet, et la notation par crochet pour quand vous utilisez réellement votre objet comme une carte de hachage .
Un bon exemple de la raison pour laquelle cette règle est si importante peut être montré dans votre exemple - puisque le code utilise la notation entre crochets à un endroit où la notation par points aurait été beaucoup plus sensible, cela rend le code plus difficile à lire. Et c'est une mauvaise chose, car le code est lu beaucoup plus de fois qu'il n'est écrit .
Dans certains cas, vous devez utiliser la notation entre crochets même si l'utilisation de la notation par points était plus judicieuse:
si un membre d'un objet a un nom contenant un ou plusieurs espaces ou tout autre caractère spécial, vous ne pouvez pas utiliser la notation par points: foo.some method()
ne fonctionne pas, mais le foo["some method"]()
fait;
si vous devez accéder dynamiquement aux membres d'un objet, vous êtes également bloqué en utilisant la notation entre crochets;
Exemple:
for(var i = 0; i < 10; ++i) {
foo["method" + i]();
}
L'essentiel est que vous devez utiliser la syntaxe des crochets lorsque vous utilisez l'objet comme une carte de hachage ( foods["burger"].eat()
) et la syntaxe des points lorsque vous travaillez avec des champs et des méthodes "réels" ( enemy.kill()
). Avec Javascript étant un langage dynamique, la ligne entre les champs et les méthodes "réels" d'un objet et les "autres" données stockées peut devenir assez floue. Mais tant que vous ne les mélangez pas de manière confuse, tout devrait bien se passer.
Maintenant, passons au reste de votre question (enfin!: P).
comment puis-je être sûr que la méthode sera toujours membre de obj
Tu ne peux pas. Essayez-le. Essayez d'appeler derp
sur une chaîne. Vous obtiendrez une erreur dans les lignes de:
Uncaught TypeError: Object a has no method 'derp'
C'est une fonction générique d'appeler TOUTES les méthodes sur TOUT objet. Mais cela signifie-t-il que la méthode spécifiée sera déjà un membre implicite de l'objet spécifié?
Oui, dans votre cas, ce devrait être le cas. Sinon, vous vous retrouvez avec l'erreur que j'ai mentionnée ci-dessus. Cependant, vous n'avez pas besoin de l'utiliser return obj[method]();
dans la callMethod()
fonction. Vous pouvez ajouter votre propre fonctionnalité qui sera ensuite utilisée par la fonction de carte. Voici une méthode codée en dur qui transforme toutes les lettres en lettres majuscules:
function makeCap()
{
return function(obj) {
return obj.toUpperCase();
}
}
var caps2 = map(['a', 'b', 'c'], makeCap()); // ['A','B','C']
console.log(caps2)
Le code du didacticiel auquel vous avez lié utilise des fonctions partielles . C'est un concept délicat en soi. En lire plus sur ce sujet devrait aider à rendre les choses plus claires que je ne pourrais jamais les faire.
Remarque: il s'agit du code de la fonction de carte utilisé par le code de la question, source ici .
function map(arr, iterator) {
var narr = [];
for (var i = 0; i < arr.length; i++) narr.push(iterator(arr[i], i));
return narr;
}
arr[5]
. Si les numéros où les noms d'identification valides , vous pouvez utiliser la notation par points:arr.5
.