web-dev-qa-db-fra.com

Est-il possible d'avoir un commentaire à l'intérieur d'une Template-String es6?

Disons que nous avons une chaîne de modèles es6 multiligne pour décrire par exemple quelques paramètres d'URL pour une demande:

const fields = `
    id,
    message,
    created_time,
    permalink_url,
    type
`;

Existe-t-il un moyen d'avoir des commentaires à l'intérieur de cette chaîne de modèle de backtick? Comme:

const fields = `
    // post id
    id,
    // post status/message
    message,
    // .....
    created_time,
    permalink_url,
    type
`;
18
lukash

Non.

Cette syntaxe est valide, mais renvoie simplement une chaîne contenant \n// post id\nid, plutôt que de supprimer les commentaires et de créer une chaîne sans eux.

Si vous regardez §11.8.6 de la spécification , vous pouvez voir que le seul jeton reconnu entre les délimiteurs de backtick est TemplateCharacters , qui accepte les séquences d'échappement, les sauts de ligne et les caractères normaux. Dans §A.1 , SourceCharacter est défini comme étant tout point Unicode (sauf ceux exclus en 11.8.6).

8
ssube

Option 1: interpolation

Nous pouvons créer des blocs interpolation qui renvoient une chaîne vide et y incorporer les commentaires.

const fields = `
  id, ${ /* post id */'' }
  message, ${ /* post status/message */'' }
  created_time,
  permalink_url,
  type
`;

console.log(fields);

Option 2: modèles balisés

En utilisant modèles balisés nous pouvons effacer les commentaires et reconstruire les chaînes. Voici une simple fonction commented qui utilise Array.map() , String.replace() , et une expression régulière (qui nécessite certains travaux) pour effacer les commentaires et renvoyer la chaîne propre:

const commented = (strings, ...values) => {
  const pattern = /\/{2}.+$/gm; // basic idea

  return strings
    .map((str, i) => 
      `${str}${values[i] !== undefined ? values[i] : ''}`)
    .join('')
    .replace(pattern, '');
};

const d = 10;
const fields = commented`
  ${d}
  id, // post ID
  ${d}
  message, // post/status message
  created_time, // ...
  permalink_uri,
  type
`;

console.log(fields);
57
Ori Drori

Je sais que c'est une vieille réponse, mais en voyant les réponses ci-dessus, je me sens obligé à la fois de répondre à la question pure, puis de répondre à l'esprit de la question du demandeur.

Pouvez-vous utiliser des commentaires dans des chaînes littérales de modèle?

Oui. Oui, vous pouvez. Mais ce n'est pas joli.

const fields = `
    id, ${/* post ID */''}
    message, ${/* post/status message */''}
    created_time, ${/*... */''}
    permalink_url,
    type
`;

Notez que vous devez mettre '' (Une chaîne vide) dans le ${ } accolades pour que Javascript ait une expression à insérer. Ne pas le faire entraînera une erreur d'exécution. Les citations peuvent aller n'importe où en dehors du commentaire.

Je ne suis pas un grand fan de cela. C'est assez moche et rend les commentaires difficiles, même si le basculement des commentaires devient difficile dans la plupart des IDE.

Personnellement, j'utilise des modèles de chaînes dans la mesure du possible, car ils sont une fraction plus efficaces que les chaînes standard et capturent littéralement tout le texte que vous voulez, la plupart du temps sans s'échapper. Vous pouvez même y mettre des appels de fonction!

La chaîne dans l'exemple ci-dessus sera un peu étrange et potentiellement inutile pour ce que vous recherchez, cependant, car il y aura un saut de ligne initial, un espace supplémentaire entre la virgule et le commentaire, ainsi qu'une finale supplémentaire saut de ligne. La suppression de cet espace indésirable pourrait être un petit coup de performances. Vous pouvez utiliser une expression régulière pour cela, pour la vitesse et l'efficacité, bien que ... plus à ce sujet ci-dessous ...

.

Maintenant, pour répondre à l'intention de la question:

Comment écrire une chaîne de liste séparée par des virgules, avec des commentaires sur chaque ligne?

const fields = [
    "id", // post ID
    "message", // post/status message
    "created_time", //...
    "permalink_url",
    "type"
].join(",\n");

Rejoindre un tableau est une façon ... (comme suggéré par @ jared-smith)

Toutefois, dans ce cas, vous créez un tableau, puis vous supprimez immédiatement les données organisées lorsque vous affectez uniquement la valeur de retour de la fonction join(). Non seulement cela, mais vous créez un pointeur de mémoire pour chaque chaîne du tableau, qui ne sera pas récupéré jusqu'à la fin de la portée. Dans ce cas, il pourrait être plus utile de capturer le tableau, de se joindre à la volée selon les besoins, ou d'utiliser un modèle littéral et de commenter différemment votre implémentation, comme le style ghostDoc.

Il semble que vous n'utilisiez que des littéraux de modèle afin de satisfaire un désir de ne pas avoir de guillemets sur chaque ligne, minimisant la dissonance cognitive entre les paramètres de requête `` chaîne '' tels qu'ils apparaissent dans l'URL et le code. Vous devez savoir que cela préserve les sauts de ligne, et je doute que vous le vouliez. Considérez plutôt:

/****************
 * Fields:
 *   id : post ID
 *   message : post/status message
 *   created_time : some other comment...
 */
const fields = `
    id,
    message,
    created_time,
    permalink_uri,
    type
`.replace(/\s/g,'');

Cela utilise une expression régulière pour filtrer tous les espaces blancs, tout en conservant la liste lisible et réorganisable. Tout ce que le littéral regex fait est de capturer les espaces, puis la méthode replace remplace le texte capturé par '' (Le g à la fin indique simplement au regex de ne pas s'arrêter à la première correspondance qu'il trouve , dans ce cas, le premier caractère de nouvelle ligne.)

ou, plus méchamment, vous pouvez simplement mettre les commentaires directement dans votre modèle littéral, puis les supprimer avec une expression régulière:

const fields = `
    id, // post ID
    message, // post/status message
    created_time, // ...
    permalink_uri,
    type
`.replace(/\s+\/\/.*\*\/\n/g,'').replace(/\s/g,'');

Ce premier regex trouvera et remplacera par une chaîne vide ('') Toutes les instances de: un ou plusieurs espaces blancs qui précèdent une double barre oblique (chaque barre oblique est échappée par une barre oblique inverse) suivie par un espace blanc et le nouveau caractère de ligne . Si vous vouliez utiliser des commentaires /* multiline */, Cette expression régulière devient un peu plus complexe, vous devrez ajouter un autre .replace() à la fin:

.replace(/\/\*.*\*\//g,'')

Cette expression régulière ne peut être supprimée qu'après avoir supprimé les nouvelles lignes \n, Ou l'expression régulière ne correspondra pas au commentaire qui n'est plus multiligne. Cela ressemblerait à quelque chose comme ceci:

const fields = `
    id, // post ID
    message, /* post/
                status message */
    created_time, // ...
    permalink_uri,
    type
`.replace(/\s+\/\/.*\n/g,'').replace(/\s/g,'').replace(/\/\*.*\*\//g,'');

Tout ce qui précède se traduira par cette chaîne:

"id,message,created_time,permalink_uri,type"

Il y a probablement un moyen de le faire avec une seule expression régulière, mais cela dépasse vraiment la portée ici. Et d'ailleurs, je vous encourage à tomber amoureux des regex en jouant avec eux vous-même!

Je vais essayer d'obtenir un https://jsperf.com/ plus tard. Je suis super curieux maintenant!

9
Metagrapher

N'utilisez simplement pas de chaînes de modèle:

const fields = [
    'id',  // comment blah blah
    'message',
    'created_time',
    'permalink_url',
    'type'
].join(',');

Vous payez le coût du tableau et de la méthode lors de l'initialisation (en supposant que le JIT n'est pas assez intelligent pour l'optimiser complètement).

Comme indiqué par ssube, la chaîne résultante ne conservera pas les sauts de ligne ou les espaces. Cela dépend de votre importance, vous pouvez ajouter manuellement '' et '\ n' si nécessaire ou décider que vous n'avez pas vraiment besoin de commentaires en ligne.

METTRE À JOUR

Notez que le stockage de données programmatiques dans des chaînes est généralement considéré comme un mauvaise idée : stockez-les plutôt en tant que variables nommées ou propriétés d'objet. Étant donné que votre commentaire reflète votre conversion d'un tas de choses en une chaîne de requête URL:

const makeQueryString = (url, data) => {
  return url + '?' + Object.keys(data)
    .map(k => `${k}=${encodeURIComponent(data[k))})
    .join('&');
};

let qs = makeQueryString(url, {
  id: 3,
  message: 'blah blah',
  // etc.
});

Vous avez maintenant des éléments plus faciles à modifier, à comprendre, à réutiliser et plus transparents pour les outils d'analyse de code (comme ceux de votre IDE de votre choix).

2
Jared Smith