Les chaînes de caractères, représentées par
l'objetString
, ont déjà été manipulées au sein de ce cours, mais il
reste bien des choses à voir à leur propos ! Nous allons dans un premier temps découvrir les types primitifs car
cela nous sera nécessaire pour vraiment parler des objets commeString
,RegExp
et
autres que nous verrons par la suite.
Nous avons vu, tout au long du cours, que les chaînes de caractères
étaient des objetsString
, les tableaux
desArray
, etc. C'est toujours vrai mais il convient de nuancer ces
propos en introduisant le concept de type primitif.
Pour créer une chaîne de caractères, on utilise généralement cette syntaxe :
var myString = "Chaîne de caractères primitive";
Cet exemple crée ce que l'on appelle
une chaîne de caractères primitive, qui n'est pas un objetString
.
Pour instancier un objetString
, il faut faire comme ceci :
var myRealString = new String("Chaîne");
Cela est valable pour les autres objets :
var myArray = []; // Tableau primitif
var myRealArray = new Array();
var myObject = {}; // Objet primitif
var myRealObject = new Object();
var myBoolean = true; // Booléen primitif
var myRealBoolean = new Boolean("true");
var myNumber = 42; // Nombre primitif
var myRealNumber = new Number("42");
Ce que nous avons utilisé jusqu'à présent était en fait des types primitifs, et non des instances d'objets.
Quelle est la différence entre un type primitif et une instance ?
La différence est minime pour nous, développeurs.
Prenons l'exemple de la chaîne de caractères : à chaque fois que nous allons faire une opération sur une chaîne
primitive, le JavaScript va automatiquement convertir cette chaîne en une instance temporaire
deString
, de manière à pouvoir utiliser les propriétés et méthodes
fournies par l'objetString
. Une fois les opérations terminées,
l'instance temporaire est détruite.
Au final, utiliser un type
primitif ou une instance revient au même du point de vue de l'utilisation. Mais il subsiste de légères différences
avec l'opérateurinstanceof
qui peut retourner de drôles de résultats…
Pour une raison ou une autre, imaginons que l'on veuille savoir de quelle instance est issu un objet :
var myString = 'Chaîne de caractères';
if (myString instanceof String) {
// Faire quelque chose
}
La condition sera fausse ! Et c'est
bien normal puisquemyString
est une chaîne primitive et non une
instance deString
. Pour tester le type primitif, il convient
d'utiliser l'opérateurtypeof
:
if (typeof myString === 'string') {
// Faire quelque chose
}
typeof
permet de vérifier le type primitif (en anglais on parle de
datatype). Mais ici aussi faites attention au piège, car la forme primitive d'une instance
deString
est…object
:
alert(typeof myRealString); // Affiche : « object »
Il faudra donc faire bien attention en
testant le type ou l'instance d'un objet ! Il est même d'ailleurs déconseillé de faire ce genre de tests vu le
nombre de problèmes que cela peut causer. La seule valeur retournée partypeof
dont
on peut être sûr, c'est"undefined"
. Nous allons étudier, plus tard
dans ce chapitre, une solution pour tester si une variable contient une chaîne de caractères.
L'objetString
est
l'objet que vous manipulez depuis le début du tutoriel : c'est lui qui gère les chaînes de caractères.
String
ne possède qu'une seule
propriété,length
, qui retourne le nombre de caractères contenus dans
une chaîne. Les espaces, les signes de ponctuation, les chiffres… sont considérés comme des caractères. Ainsi, cette
chaîne de caractères contient 21 caractères :
alert('Ceci est une chaîne !'.length);
Mais ! C'est quoi cette manière d'écrire du code ?
En fait, il n'est pas toujours obligatoire de déclarer une variable pour utiliser les propriétés et les méthodes d'un objet. En effet, vous pouvez écrire directement le contenu de votre variable et utiliser une de ses propriétés ou de ses méthodes, comme c'est le cas ici. Notez cependant que cela ne fonctionne pas avec les nombres sous forme primitive car le point est le caractère permettant d'ajouter une ou plusieurs décimales. Ainsi, ce code générera une erreur :
0.toString(); // Une erreur se produira si vous exécutez ce code
String
possède quelques méthodes qui sont pour la plupart assez
intéressantes mais basiques. Le JavaScript est un langage assez simple, qui ne contient pas énormément de méthodes
de base. C'est un peu l'inverse du PHP qui contient une multitude de fonctions pour réaliser un peu tout et
n'importe quoi. Par exemple, le PHP possède une fonction pour mettre la première lettre d'une chaîne en majuscule,
alors qu'en JavaScript il faudra nous-mêmes récupérer le premier caractère et le mettre en majuscule. Le JavaScript
fournit juste quelques méthodes de base, et ce sera à vous de coder vous-mêmes d'autres méthodes ou fonctions selon
vos besoins.
toLowerCase()
ettoUpperCase()
toLowerCase()
ettoUpperCase()
permettent
respectivement de convertir une chaîne en minuscules et en majuscules. Elles sont pratiques pour réaliser différents
tests ou pour uniformiser une chaîne de caractères. Leur utilisation est simple :
var myString = 'tim berners-lee';
myString = myString.toUpperCase(); // Retourne : « TIM BERNERS-LEE »
La méthodecharAt()
permet
de récupérer un caractère en fonction de sa position dans la chaîne de caractères. La méthode reçoit en paramètre la
position du caractère :
var myString = 'Pauline';
var first = myString.charAt(0); // P
var last = myString.charAt(myString.length - 1); // e
En fait, les chaînes de caractères
peuvent être imaginées comme des tableaux, à la différence qu'il n'est pas possible d'accéder aux caractères en
utilisant les crochets : à la place, il faut utilisercharAt()
.
La méthodecharCodeAt()
fonctionne
commecharAt()
à la différence que ce n'est pas le caractère qui est
retourné mais le code ASCII du caractère.
fromCharCode()
permet
de faire plus ou moins l'inverse decharCodeAt()
: instancier une
nouvelle chaîne de caractères à partir d'une chaîne ASCII, dont chaque code est séparé par une virgule. Son
fonctionnement est particulier puisqu'il est nécessaire d'utiliser l'objetString
lui-même
:
var myString = String.fromCharCode(74, 97, 118, 97, 83, 99, 114, 105, 112, 116); // le mot JavaScript en ASCII
alert(myString); // Affiche : « JavaScript »
Mais quel est l'intérêt d'utiliser les codes ASCII ?
Ce n'est pas très fréquent, mais cela peut être utile dans un cas
bien particulier : détecter les touches du clavier. Admettons qu'il faille savoir quelle touche du clavier à été
pressée par l'utilisateur. Pour cela, on utilise la propriétékeyCode
de
l'objetEvent
:
onkeyup="listenKey(event)"
La
fonctionlistenKey()
peut être écrite comme suit :
function listenKey(event) {
var key = event.keyCode;
alert('La touche numéro ' + key + ' a été pressée. Le caractère ' + String.fromCharCode(key) + ' a été inséré.');
}
event.keyCode
retourne le code ASCII qui correspond au caractère
inséré par la touche. Pour la touche J, le code ASCII est 74 par exemple.
trim()
trim()
sert à supprimer les espaces avant et après une chaîne de
caractères. C'est particulièrement utile quand on récupère des données saisies dans une zone de texte, car
l'utilisateur est susceptible d'avoir laissé des espaces avant et après son texte, surtout s'il a fait un
copier/coller.
indexOf()
etlastIndexOf()
La
méthodeindexOf()
est utile dans deux cas de figure :
Savoir si une chaîne de caractères contient un caractère ou un morceau de chaîne ;
Savoir à quelle position se trouve le premier caractère de la chaîne recherchée.
indexOf()
retourne
la position du premier caractère trouvé, et s'il n'y en a pas la valeur -1 est retournée.
var myString = 'Le JavaScript est plutôt cool';
var result = myString.indexOf('JavaScript');
if (result > -1) {
alert('La chaîne contient le mot "JavaScript" qui débute à la position ' + result);
}
Ce code a pour but de savoir si la
chaînemyString
contient la chaîne « JavaScript ». La position de la
première occurrence de la chaîne recherchée est stockée dans la variableresult
.
Siresult
vaut -1, alors la chaîne n'a pas été trouvée. Si, en
revanche,result
vaut 0 (le premier caractère) ou une autre valeur, la
chaîne est trouvée.
SiindexOf()
retourne
la position de la première occurrence trouvée,lastIndexOf()
retourne
la position de la dernière.
Notons que ces deux fonctions possèdent chacune un deuxième argument qui permet de spécifier à partir de quel index la recherche doit commencer.
indexOf()
etlastIndexOf()
Une particularité intéressante et relativement méconnue du JavaScript est son caractère tilde ~. Il s'agit de l'opérateur binaire « NOT » qui a pour rôle d'inverser tous les bits d'une valeur. Comme le binaire ne nous sert pas à grand chose dans le cadre de notre apprentissage, il est plus logique d'expliquer son influence sur les nombres en base décimale : le tilde incrémente la valeur qui le suit et y ajouter une négation, comme ceci :
alert(~2); // Affiche : « -3 »
alert(~3); // Affiche : « -4 »
alert(~-2); // Affiche : « 1 »
Hum... Ça ne servirait pas un peu à rien, ce truc ?
Eh bien pas tant que ça ! Le tilde est effectivement très peu utile en temps normal, mais dans le cadre d'une utilisation avec les deux méthodes étudiées, il est redoutablement efficace pour détecter si une chaîne de caractères contient un caractère ou un morceau de chaîne. En temps normal nous ferions comme ceci :
var myString = 'Le JavaScript est plutôt cool';
if (myString.indexOf('JavaScript') != -1) {
alert('La chaîne contient bien le mot "JavaScript".');
}
Mais au final il est possible d'ajouter un simple petit tilde ~ à la ligne 3 :
var myString = 'Le JavaScript est plutôt cool';
if (~myString.indexOf('JavaScript')) {
alert('La chaîne contient bien le mot "JavaScript".');
}
En faisant cela, dans le cas où le
résultat serait -1, celui-ci va alors se retrouver incrémenté et arriver à 0, ce qui donnera donc une évaluation
àfalse
pour notre chaîne de caractères. La valeur -1 étant la seule à
pouvoir atteindre la valeur 0 avec le tilde ~, il n'y a pas d'hésitation à avoir vu que tous les autres nombres
seront évalués àtrue
!
Oui, cette technique a été conçue pour les parfaits fainéants, mais il y a fort à parier que vous vous en souviendrez.
substring()
,substr()
etslice()
Nous avons vu comment trouver la position d'une chaîne de caractères dans une autre, il est temps de voir comment extraire une portion de chaîne, à partir de cette position.
Considérons cette chaîne :
var myString = 'Thunderseb et Nesk';
Le but du jeu va être de récupérer,
dans deux variables différentes, les deux pseudonymes contenus
dansmyString
. Pour ce faire, nous allons
utilisersubstring()
.substring(a,
b)
permet d'extraire une chaîne à partir de la positiona
(incluse)
jusqu'à la positionb
(exclue).
Pour extraire « Thunderseb », il suffit de connaître la position du premier espace, puisque la position de départ vaut 0 :
var nick_1 = myString.substring(0, myString.indexOf(' '));
Pour « Nesquik69 », il suffit de
connaître la position du dernier espace : c'est à ce moment que commencera la chaîne. Comme «Nesquik69 » termine la
chaîne, il n'y a pas besoin de spécifier de deuxième paramètre poursubstring()
,
la méthode va automatiquement aller jusqu'au bout :
var nick_2 = myString.substring(myString.lastIndexOf(' ') + 1); // Ne pas oublier d'ajouter 1, pour commencer au N et non à l'espace
Une autre manière de procéder serait
d'utilisersubstr()
, la méthode sœur
desubstring()
.substr(a,
n)
accepte deux paramètres : le premier est la position de début, et le deuxième le nombre de caractères à
extraire. Cela suppose donc de connaître le nombre de caractères à extraire. Ça limite son utilisation et c'est une
méthode que vous ne rencontrerez pas fréquemment, au contraire
desubstring()
.
Une dernière méthode d'extraction existe
:slice()
.slice()
ressemble
très fortement àsubstring()
, mais avec une option en plus. Une valeur
négative est transmise pour la position de fin,slice()
va extraire la
chaîne jusqu'à la fin, en décomptant le nombre de caractères indiqué. Par exemple, si on ne veut récupérer que «
Thunder », on peut faire comme ceci :
var nick_1 = 'Thunderseb'.slice(0, -3);
split()
La
méthodesplit()
permet de couper une chaîne de caractères à chaque fois
qu'une sous-chaîne est rencontrée. Les « morceaux » résultant de la coupe de la chaîne sont placés dans un tableau.
var myCSV = 'Pauline,Guillaume,Clarisse'; // CSV = Comma-Separated Values
var splitted = myCSV.split(','); // On coupe à chaque fois qu'une virgule est rencontrée
alert(splitted.length); // 3
Dans cet
exemple,splitted
contient un tableau contenant trois éléments : «
Pauline », « Guillaume » et « Clarisse ».
Nous l'avons vu plus haut,
l'instructiontypeof
est utile, mais la seule valeur de confiance
qu'elle retourne est"undefined"
. En effet, lorsqu'une variable
contient le type primitif d'une chaîne de caractères,typeof
retourne
bien la valeur"string"
, mais si la variable contient une instance
deString
alors on obtient en retour la
valeur"object"
. Ce qui fait
quetypeof
ne fonctionne que dans un cas sur deux, il nous faut donc
une autre solution pour gérer le deuxième cas.
Et cette
solution existe ! Il s'agit de la méthodevalueOf()
qui est héritée
deObject
. Cette méthode renvoie la valeur primitive de n'importe quel
objet. Ainsi, si on crée une instance deString
:
var string_1 = new String('Test');
et que l'on récupère le résultat de sa
méthodevalueOf()
dans la
variablestring_2
:
var string_2 = string_1.valueOf();
alors
l'instructiontypeof
montre bien
questring_1
est une instance
deString
et questring_2
est
une valeur primitive :
alert(typeof string_1); // Affiche : « object »
alert(typeof string_2); // Affiche : « string »
Grâce à cette méthode, il devient bien plus simple de vérifier si une variable contient une chaîne de caractères. Voici notre code final :
function isString(variable) {
return typeof variable.valueOf() === 'string'; // Si le type de la valeur primitive est « string » alors on retourne « true »
}
D'accord, cette fonction va s'exécuter correctement si on envoie
une instance deString
. Mais que va
renvoyervalueOf()
si on passe une valeur primitive à notre
fonction ?
Eh bien, tout simplement la même valeur.
Expliquons-nous :valueOf()
retourne la valeur primitive d'un objet,
mais si cette méthode est utilisée sur une valeur qui est déjà de type primitif, alors elle va retourner la même
valeur primitive, ce qui convient très bien vu que dans tous les cas il s'agit de la valeur primitive que nous
souhaitons analyser !
Pour vous convaincre, testez donc par vous-mêmes :
alert(isString('Test')); // Affiche : « true »
alert(isString(new String('Test'))); // Affiche : « true »
Notre fonction marche dans les deux cas. Alors, est-ce qu'en pratique vous aurez besoin d'une fonction pareille ? La réponse est : assez peu… Mais il est toujours bon de savoir comment s'en servir, non ?
Et enfin, à titre d'information, sachez qu'il est aussi possible
d'obtenir une instanciation d'objet à partir d'un type primitif (autrement dit, on fait l'inverse
devalueOf()
), il suffit de procéder de cette manière :
var myString = Object('Mon texte');
Pour
rappel,Object
est l'objet dont tous les autres objets (tel
queString
) héritent. Ainsi, en créant une instance
deObject
avec un type primitif en paramètre, l'objet instancié sera de
même type que la valeur primitive. En clair, si vous passez en paramètre un type
primitifstring
alors vous obtiendrez une instance de
l'objetString
avec la même valeur passée en paramètre.
Il existe des
objets et des types primitifs. Si leur utilisation semble identique, il faut faire attention lors des tests avec
les
opérateursinstanceof
ettypeof
.
Mais heureusementvalueOf()
sera d'une aide précieuse.
Il est préférable d'utiliser les types primitifs, comme nous le faisons depuis le début de ce cours.
String
fournit des méthodes pour manipuler les caractères : mettre
en majuscule ou en minuscule, récupérer un caractère grâce à sa position et supprimer les espaces de part et
d'autre de la chaîne.
String
fournit aussi des méthodes pour rechercher, couper et
extraire.
L'utilisation
du caractère tilde est méconnue, mais peut se révéler très utile en couple
avecindexOf()
oulastIndexOf()
.