【问题标题】:Is it possible to have a comment inside a es6 Template-String?是否可以在 es6 模板字符串中添加评论?
【发布时间】:2019-09-16 01:51:04
【问题描述】:

假设我们有一个多行 es6 模板字符串来描述例如请求的一些 URL 参数:

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

有没有办法在反引号模板字符串中包含 cmets?喜欢:

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

【问题讨论】:

    标签: javascript ecmascript-6 backticks template-strings


    【解决方案1】:

    只是不要使用模板字符串:

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

    您在初始化时支付数组和方法调用的成本(假设 JIT 不够聪明,无法完全优化它。

    正如 ssube 所指出的,生成的字符串不会保留换行符或空格。这取决于它的重要性,如果需要,您可以手动添加 ' ' 和 '\n' 或决定您真的不需要那么严重的内联 cmets。

    更新

    请注意,将编程数据存储在字符串中通常被认为是bad idea:将它们存储为命名变量或对象属性。由于您的评论反映了您只是将一堆东西转换为 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 中的工具)更透明的东西。

    【讨论】:

    • 这会产生一个非常不同的字符串,因为它不保留换行符或空格。
    • 是的,我也考虑过这一点。并且(在我的情况下)需要删除的换行符/空格,所以我想我必须采用该解决方案。只是对它是否可能感兴趣。
    • 在我的例子中,它不是关于存储数据,而是关于一个 Graph API 请求,看起来像:/page-id/posts?fields=id,message,created_time,...,。 ..,...,...&limit=100&since=... 而且我不想将字段值存储在一个长的、不可读的字符串中。
    • @lukash 更新了答案以反映相关用例。
    • @JaredSmith 谢谢,但我认为你误会了。 URL 看起来不像 ?id=3&message=blahblah... - 但像: ?fields=id,message,created_time,type&otherstuff=1 而且我不想有一长串字段名称。
    【解决方案2】:

    选项 1:插值

    我们可以创建返回空字符串的 interpolation 块,并将 cmets 嵌入其中。

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

    选项 2:标记模板

    使用tagged templates 我们可以清除 cmets 并重建字符串。这是一个简单的 commented 函数,它使用 Array.map()String.replace() 和一个正则表达式(需要一些工作)来清除 cmets,并返回干净的字符串:

    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);

    【讨论】:

      【解决方案3】:

      我知道这是一个古老的答案,但看到上面的答案,我觉得不得不回答纯粹的问题,然后回答提问者问题的精神。

      可以在模板文字字符串中使用 cmets 吗?

      是的。是的你可以。但这并不漂亮。

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

      请注意,您必须将 ''(一个空字符串)放在 ${ } 大括号中,以便 Javascript 可以插入表达式。不这样做会导致运行时错误。引号可以放在评论之外的任何地方。

      我不是这个的忠实粉丝。它非常丑陋,并且使评论变得麻烦,更不用说在大多数 IDE 中切换 cmets 变得很困难。

      就我个人而言,我尽可能使用模板字符串,因为它们比常规字符串更有效,而且它们从字面上捕获您想要的所有文本,大部分没有转义。你甚至可以把函数调用放在那里!

      上面示例中的字符串会有点奇怪,并且对于您要查找的内容可能毫无用处,但是,因为会有一个初始换行符、逗号和注释之间的额外空格,以及一个额外的最后换行符。删除不需要的空间可能会对性能造成很小的影响。您可以为此使用正则表达式,以提高速度和效率,但...更多关于以下内容...

      .

      现在回答问题的意图:

      如何编写一个逗号分隔的列表字符串,每行都有 cmets?

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

      加入数组是一种方式...(如@jared-smith 所建议)

      但是,在这种情况下,当您只分配 join() 函数的返回值时,您正在创建一个数组,然后立即丢弃组织的数据。不仅如此,您还为数组中的每个字符串创建了一个内存指针,直到作用域结束时才会对它进行垃圾收集。在这种情况下,捕获数组、根据使用指示动态连接或使用模板文字并以不同方式注释您的实现可能更有用,例如 ghostDoc 样式。

      您似乎只使用模板文字来满足在每一行上没有引号的愿望,从而最大限度地减少“字符串”查询参数在 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,'');
      

      这使用正则表达式过滤掉所有空格,同时保持列表的可读性和可重新排列。正则表达式文字所做的只是捕获空格,然后替换方法将捕获的文本替换为''(末尾的g 只是告诉正则表达式不要在它找到的第一个匹配项处停止,在这种情况下,第一个换行符。)

      或者,最讨厌的是,您可以直接将 cmets 放入模板文字中,然后使用正则表达式剥离它们:

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

      第一个正则表达式将查找并用空字符串 ('') 替换以下所有实例:一个或多个在双斜杠之前的空白字符(每个斜杠由反斜杠转义),后跟空格和换行符.如果你想使用/* multiline */ cmets,这个正则表达式会变得有点复杂,你必须在最后添加另一个.replace()

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

      该正则表达式只能在您删除 \n 换行符后才能使用,否则正则表达式将与 now-not-multiline 注释不匹配。看起来像这样:

      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/。我现在超级好奇!

      【讨论】:

        【解决方案4】:

        没有。

        该语法是有效的,但只会返回一个包含 \n// post id\nid 的字符串,而不是删除 cmets 并创建一个没有它们的字符串。

        如果您查看§11.8.6 of the spec,您可以看到在反引号分隔符之间识别的唯一标记是TemplateCharacters,它接受转义序列、换行符和普通字符。在§A.1 中,SourceCharacter 被定义为任何 Unicode 点(11.8.6 中排除的点除外)。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2017-08-08
          • 1970-01-01
          • 2012-04-17
          • 2020-07-23
          • 2015-02-23
          • 2016-09-19
          • 2018-01-23
          相关资源
          最近更新 更多