Можно ли иметь комментарий внутри шаблона-строки es6?

Допустим, у нас есть многострочная шаблонная строка es6, например, для описания некоторых параметров URL для запроса:

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

Есть ли способ иметь комментарии внутри этого обратного шаблона-строки? Подобно:

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

5 ответов

Решение

Нет.

Этот синтаксис действителен, но просто вернет строку, содержащую \n// post id\nid вместо удаления комментариев и создания строки без них.

Если вы посмотрите на §11.8.6 спецификации, то увидите, что единственным токеном, распознаваемым между разделителями обратного ключа, является TemplateCharacters, который принимает escape-последовательности, разрывы строк и нормальные символы. В §A.1 SourceCharacter определяется как любая точка Unicode (кроме исключенных в 11.8.6).

Вариант 1: интерполяция

Мы можем создавать блоки интерполяции, которые возвращают пустую строку, и вставлять комментарии внутри них.

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

console.log(fields);

Вариант 2: помеченные шаблоны

Используя помеченные шаблоны, мы можем очистить комментарии и восстановить строки. Вот простойcommentedфункция, которая используетArray.map(), String.replace()и выражение регулярного выражения (которое требует некоторой работы) для очистки комментариев и возврата чистой строки:

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

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

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

console.log(fields);

Я знаю, что это старый ответ, но, видя ответы выше, я чувствую себя обязанным как ответить на чистый вопрос, так и затем ответить на дух вопроса аскера.

Можете ли вы использовать комментарии в шаблонных литеральных строках?

Да. Да, ты можешь. Но это не красиво.

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

Обратите внимание, что вы должны поставить '' (пустая строка) в ${ } фигурные скобки, так что Javascript имеет выражение для вставки. Невыполнение этого приведет к ошибке во время выполнения. Цитаты могут находиться где угодно за пределами комментария.

Я не большой поклонник этого. Это довольно уродливо и делает комментирование громоздким, не говоря уже о том, что переключение комментариев становится трудным в большинстве IDE.

Лично я использую строки шаблона везде, где это возможно, так как они намного эффективнее обычных строк, и они захватывают буквально весь текст, который вы хотите, в основном без экранирования. Вы даже можете делать вызовы функций там!

Строка в приведенном выше примере будет немного странной и потенциально бесполезной для того, что вы ищете, однако, будет начальный разрыв строки, дополнительный пробел между запятой и комментарием, а также дополнительный финал Разрыв строки. Удаление этого ненужного места может быть небольшим ударом по производительности. Вы можете использовать регулярные выражения для этого, для скорости и эффективности, хотя... подробнее об этом ниже...

,

Теперь ответим на вопрос:

Как написать строку списка, разделенную запятыми, с комментариями к каждой строке?

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

Присоединение к массиву - это один из способов... (как предложено @jared-smith)

Однако в этом случае вы создаете массив, а затем немедленно отбрасываете организованные данные, когда вы только назначаете возвращаемое значение join() функция. Кроме того, вы создаете указатель памяти для каждой строки в массиве, который не будет собирать мусор до конца области видимости. В этом случае может оказаться более полезным захватить массив, присоединяясь на лету, как того требует использование, или использовать литерал шаблона и по-разному комментировать вашу реализацию, например стиль ghostDoc.

Кажется, что вы используете литералы шаблонов только для того, чтобы удовлетворить желание не иметь кавычек в каждой строке, сводя к минимуму когнитивный диссонанс между параметрами запроса 'string', когда они выглядят в url и коде. Вы должны знать, что это сохраняет разрывы строк, и я сомневаюсь, что вы этого хотите. Рассмотрим вместо этого:

/****************
 * 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,'');

Это использует регулярное выражение, чтобы отфильтровать все пробелы, сохраняя при этом список читабельным и переставляемым. Все, что делает литерал regex, это захват пробелов, а затем метод replace заменяет захваченный текст на '' (g в конце просто указывает регулярному выражению не останавливаться на первом совпадении, которое он находит, в данном случае на первом символе новой строки.)

или, что самое неприятное, вы можете просто поместить комментарии прямо в литерал шаблона, а затем удалить их с помощью регулярного выражения:

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

Это первое регулярное выражение найдет и заменит пустую строку ('') все экземпляры: один или несколько пробельных символов, которые предшествуют двойной косой черте (каждая косая черта экранируется обратной косой чертой), за которой следуют пробельные символы и символ новой строки. Если вы хотите использовать /* multiline */ комментарии, это регулярное выражение становится немного сложнее, вам придется добавить еще .replace() в конце:

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

Это регулярное выражение может идти только после того, как вы удалите \n символы новой строки, или регулярное выражение не будет соответствовать комментарию, не являющемуся многострочным. Это будет выглядеть примерно так:

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

Все вышеперечисленное приведет к этой строке:

"id,message,created_time,permalink_uri,type"

Вероятно, есть способ сделать это только с одним регулярным выражением, но на самом деле это выходит за рамки. Кроме того, я бы посоветовал вам полюбить регулярные выражения, играя с ними сами!

Я постараюсь получить https://jsperf.com/ об этом позже. Мне сейчас очень любопытно!

Только не используйте строки шаблона:

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

Вы оплачиваете стоимость массива и вызова метода при инициализации (при условии, что JIT недостаточно умен, чтобы полностью его оптимизировать).

Как указывает ssube, результирующая строка не будет сохранять разрывы строк или пробелы. Это зависит от того, насколько это важно, вы можете вручную добавить ' ' и '\n', если необходимо, или решить, что вам действительно не нужны такие комментарии.

ОБНОВИТЬ

Обратите внимание, что хранение программных данных в строках обычно считается плохой идеей: вместо этого сохраняйте их как именованные переменные или свойства объекта. Поскольку ваш комментарий отражает то, что вы просто преобразовали кучу вещей в строку 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.
});

Теперь у вас есть вещи, которые легче изменить, понять, использовать повторно и сделать более прозрачными для инструментов анализа кода (например, в выбранной вами IDE).

Да, это возможно

Использовать<!-- content here -->

Другие вопросы по тегам