JavaScript continue de me surprendre et c'est un autre exemple. Je suis juste tombé sur un code que je ne comprenais pas au début. Je l'ai donc débogué et suis arrivé à cette conclusion:
alert('a'['toUpperCase']()); //alerts 'A'
Maintenant, cela doit être évident s'il toUpperCase()
est défini comme un membre de type chaîne, mais cela n'avait pas de sens pour moi au départ.
En tous cas,
toUpperCase
Est- ce que cela fonctionne parce qu'il est membre de «a»? Ou il se passe autre chose dans les coulisses?le code que je lisais a une fonction comme suit:
function callMethod(method) { return function (obj) { return obj[method](); //**how can I be sure method will always be a member of obj** } } var caps2 = map(['a', 'b', 'c'], callMethod('toUpperCase')); // ['A','B','C'] // ignoring details of map() function which essentially calls methods on every // element of the array and forms another array of result and returns it
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é?
Je suis sûr que je manque une compréhension sérieuse du concept de base des fonctions JavaScript. S'il vous plaît, aidez-moi à comprendre cela.
javascript
function
Mahesha999
la source
la source
arr[5]
. Si les numéros où les noms d'identification valides , vous pouvez utiliser la notation par points:arr.5
.5['toString']()
.Réponses:
Pour le décomposer.
.toUpperCase()
est une méthode deString.prototype
'a'
est une valeur primitive, mais est convertie en sa représentation d'objetAlors
est l'accès via la notation entre crochets sur la propriété
toUpperCase
, à partir deString.prototype
. Puisque cette propriété fait référence à une méthode , nous pouvons l'invoquer en attachant()
la source
foo.bar
etfoo['bar']
sont égaux donc le code que vous avez publié est le même queLorsque vous utilisez
foo[bar]
(notez le manque de guillemets), vous n'utilisez pas le nom littéralbar
mais la valeur quebar
contient la variable . Ainsi, l'utilisation de lafoo[]
notation au lieu defoo.
vous permet d'utiliser un nom de propriété dynamique.Jetons un œil à
callMethod
:Tout d'abord, il renvoie une fonction qui prend
obj
comme argument. Lorsque cette fonction est exécutée, elle fera appelmethod
à cet objet. La méthode donnée doit donc simplement exister soit surobj
elle-même, soit quelque part sur sa chaîne prototype.Dans le cas où
toUpperCase
cette méthode vient deString.prototype.toUpperCase
- il serait plutôt stupide d'avoir une copie séparée de la méthode pour chaque chaîne qui existe.la source
Vous pouvez accéder aux membres de n'importe quel objet avec une
.propertyName
notation ou une["propertyName"]
notation. C'est la caractéristique du langage JavaScript. Pour être sûr que le membre se trouve dans l'objet, vérifiez simplement s'il est défini:la source
Fondamentalement, javascript traite tout comme un objet, ou plutôt chaque objet peut être vu comme un dictionnaire / tableau associatif. Et les fonctions / méthodes sont définies exactement de la même manière pour l'objet - comme une entrée dans ce tableau associatif.
Donc, essentiellement, vous référencez / appelez (notez le ' () ') la propriété 'toUpperCase', de l'objet 'a' (qui est un type chaîne, dans ce cas).
Voici un code du haut de ma tête:
la source
anyObject['anyPropertyName']
est le même queanyObject.anyPropertyName
lorsqueanyPropertyName
n'a pas de caractères problématiques.Voir Travailler avec des objets , à partir du MDN.
La
toUpperCase
méthode est attachée au type String. Lorsque vous appelez une fonction sur une valeur primitive, ici'a'
, elle est automatiquement promue en objet, ici une chaîne :Vous pouvez voir que la fonction existe en vous connectant
String.prototype.toUpperCase
.la source
Donc en Javascript,
objects
c'estobjects
. C'est qu'ils sont de cette nature{}
. Les propriétés des objets peuvent être définies à l'aide de l'une des options suivantes:a.greeting = 'hello';
oua['greeting'] = 'hello';
. Les deux méthodes fonctionnent.La récupération fonctionne de la même manière.
a.greeting
(sans guillemets) est'hello'
,a['greeting']
est'hello'
. Exception: si la propriété est un nombre, seule la méthode des crochets fonctionne. La méthode des points ne fonctionne pas.Il en
'a'
va de même pour un objet dont la'toUpperCase'
propriété est en fait une fonction. Vous pouvez récupérer la fonction et l'appeler ultérieurement dans les deux cas:'a'.toUpperCase()
ou'a'['toUpperCase']()
.Mais imo la meilleure façon d'écrire la fonction de carte serait alors:
var caps = ['a','b','c'].map( function(char) { return char.toUpperCase(); } )
Qui a alors besoin de la
callMethod
fonction?la source
Chaque objet JavaScript est une table de hachage, vous pouvez donc accéder à ses membres en spécifiant une clé. par exemple, si une variable est une chaîne, elle doit avoir la fonction toUpperCase. Vous pouvez donc l'invoquer en
donc, en ligne str, vous pourriez avoir ci-dessous
la source
toUpperCase est une méthode javascript standard: https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/String/toUpperCase
La raison pour laquelle cela fonctionne
'a'['toUpperCase']()
est que la fonction toUpperCase est une propriété de l'objet chaîne'a'
. Vous pouvez référencer les propriétés d'un objet à l'aide deobject[property]
ouobject.property
. La syntaxe 'a''toUpperCase' indique que vous faites référence à la propriété 'toUppercase' de l'objet chaîne 'a', puis que vous l'appelez ().la source
Non. Quelqu'un pourrait passer dans un objet qui
toUpperCase
; outoUpperCase
qui n'est pas une fonctionDans le premier cas, une erreur sera levée car l'accès à une propriété qui n'existe pas revient
undefined
, et nous ne pouvons pas invoquer enundefined
tant que fonction.Dans le second cas, une erreur sera levée car encore une fois, nous ne pouvons pas invoquer une non-fonction en tant que fonction.
N'oubliez pas que JavaScript est un langage très lâche. Il n'y a que peu ou pas de vérification de type sauf si et jusqu'à ce qu'il le soit. Le code que vous avez montré fonctionne dans certains cas car, dans ces cas, l'objet transmis a une propriété nommée
toUpperCase
, c'est-à-dire une fonction.Le fait que l'
obj
argument ne soit pas garanti d'avoir les bons types de propriétés ne dérange pas du tout JavaScript, pour ainsi dire. Il adopte une attitude "attendre et voir" et ne génère pas d'erreur tant qu'un problème réel ne se produit pas au moment de l'exécution.la source
Presque tout en javascript peut être traité comme un objet. Dans votre cas, l'alphabet lui-même agit comme un objet chaîne et
toUpperCase
peut être invoqué comme méthode. Les crochets ne sont qu'un moyen alternatif d'accéder aux propriétés des objets et puisqu'iltoUpperCase
s'agit d'une méthode, le support simple()
est nécessaire à côté de la['toUpperCase']
formation['toUpperCase']()
.'a'['toUpperCase']()
est équivalent à'a'.toUpperCase()
la source
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 taperalert
, 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 contenantundefined
, car elle n'a reçu aucun paramètre. Nous pouvons désormais utiliser ces connaissances pour déchiffrer votre code, qui devient:Ce qui est beaucoup plus lisible.
En fait, un bon moyen de mieux comprendre cela est d'exécuter le Javascript suivant:
Cela appelle
alert
en lui passant un objet fonction, égalementalert
, sans exécuter également la deuxième alerte. Ce qui s'affiche (au moins dans Chrome 26) est le suivant:Appel:
affiche deux boîtes de message consécutives contenant
undefined
. Ceci est facile à expliquer: l'intérieuralert()
est exécuté en premier, s'afficheundefined
(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 égalementundefined
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: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 lefoo["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:
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).
Tu ne peux pas. Essayez-le. Essayez d'appeler
derp
sur une chaîne. Vous obtiendrez une erreur dans les lignes de: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 lacallMethod()
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: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 .
la source
Si vous demandez comment cela fonctionne réellement, c'est ainsi que je le lis. Ok, c'est une simple fonction mathématique. Pour le comprendre, vous devez regarder le tableau ascii. Qui attribue une valeur numérique à chaque lettre. Pour le dissimuler, le concurrent utilise simplement une instruction logique pour le convertir, par exemple, si (ChcrValue> 80 && charValue <106) // Il s'agit de l'ensemble des lettres minuscules, puis charValue = charValue - 38; // la distance entre l'ensemble inférieur et l'ensemble supérieur
c'est aussi simple que cela, je n'ai pas pris la peine de rechercher les valeurs correctes, mais cela déplace essentiellement toutes les lettres minuscules en majuscules.
la source
'a'['toUpperCase']()
travailler. Mais le malentendu est compréhensible, si quelqu'un n'a pas lu la question.text-transform: uppercase
été ajouté, j'étais à bout de mots sur la façon dont JS a réussi à changer le cas, a dissipé le doute et a appris une chose ou deux. Merci beaucoup.