【问题标题】:Javascript heredocJavascript heredoc
【发布时间】:2011-05-21 13:23:26
【问题描述】:

我需要像 JavaScript 中的 heredoc 这样的东西。你对此有什么想法吗?我需要跨浏览器功能。

我发现了这个:

heredoc = '\
<div>\
    <ul>\
        <li><a href="#zzz">zzz</a></li>\
    </ul>\
</div>';

我认为这对我有用。 :)

【问题讨论】:

  • stackoverflow.com/questions/805107/… 的副本,其中有一些更详细的答案。
  • 必须加“\”让我每次都皱眉。恕我直言,没有多行字符串的正常语法是完全不合理的。他们可以在任何给定的版本中添加它,但他们没有。
  • 不幸的是 JavaScript 不支持 heredoc 之类的东西。

标签: javascript heredoc


【解决方案1】:

试试ES6字符串模板,你可以做类似的事情

var hereDoc = `
This
is
a
Multiple
Line
String
`.trim()


hereDoc == 'This\nis\na\nMultiple\nLine\nString'

=> true

即使在带有TypeScript 的旧版浏览器中,您也可以使用这个强大的功能

【讨论】:

  • 这适用于您只想要多行字符串的情况。但是,由于您无法真正更改包含字符串的符号,因此它并不是真正的 heredoc。
  • 请注意,最初的问题是在 5 年前 ES6 可用之前提出的。这是前进的最佳实践,因为性能也更好。
  • @HenryTseng,您是否建议这个问题的答案应该针对 5 年前存在的古代技术量身定制?如果问题仍然悬而未决,那么它应该利用随着时间的推移而创造的新技术。这样,遇到相同问题的新用户可以在这里找到“非考古”信息。
  • 不,我在评论为什么该解决方案之前没有更突出。如果没有任何兼容性问题,这似乎绝对是受支持的前进方式。
【解决方案2】:

不,很遗憾 JavaScript 不支持 heredoc 之类的东西。

【讨论】:

  • 我知道,但我希望能找到 heredoc hack :)
  • 类似于解析函数的 cmets(但在 ie/firefox 中不起作用)=
【解决方案3】:

这个怎么样:

function MyHereDoc(){
/*HERE
<div>
   <p>
      This is written in the HEREDOC, notice the multilines :D.
   </p>
   <p>
      HERE
   </p>
   <p>
      And Here
   </p>
</div>
HERE*/
    var here = "HERE";
    var reobj = new RegExp("/\\*"+here+"\\n[\\s\\S]*?\\n"+here+"\\*/", "m");
    str = reobj.exec(MyHereDoc).toString();
    str = str.replace(new RegExp("/\\*"+here+"\\n",'m'),'').toString();
    return str.replace(new RegExp("\\n"+here+"\\*/",'m'),'').toString();
}

//Usage 
document.write(MyHereDoc());

只需将“/*HERE”和“HERE*/”替换为所选单词即可。

【讨论】:

  • 是否所有浏览器/引擎都返回 Function.toString() 中的 cmets?这很聪明
  • 如果您在 heredoc 中有结束评论 */ 将无法使用。
  • 我建议使用 Nate Ferrero 的答案,因为他的例子更加精致和优化。我的使用 3 个单独的正则表达式调用,并且更多的是概念证明。
  • 非常聪明......但你不能保证它会在未来工作。它过于依赖于实现,不是一个好的做法。
【解决方案4】:

基于 Zv_oDD 的回答,我创建了一个类似的函数以便于重用。

警告:这是许多 JS 解释器的非标准功能,可能会在某些时候被删除,但由于我正在构建一个仅在 Chrome 中使用的脚本,所以我使用它!对于面向客户的网站,不要永远依赖它!

// Multiline Function String - Nate Ferrero - Public Domain
function heredoc(fn) {
  return fn.toString().match(/\/\*\s*([\s\S]*?)\s*\*\//m)[1];
};

用途:

var txt = heredoc(function () {/*
A test of horrible
Multi-line strings!
*/});

返回:

"A test of horrible
Multi-line strings!"

注意事项:

  1. 文本在两端被修剪,因此两端的任何多余空格都可以。

编辑:

2/2/2014 - 更改为完全不与函数原型混淆,而是使用名称 heredoc。

5/26/2017 - 更新了空格以反映现代编码标准。

【讨论】:

  • 我会使用 hereDoc() 作为我的函数名,但是这段代码可以很好地将我的 40k 行日志转储加载到 Chrome 控制台中的变量中
  • 为什么要创建一个函数的实例并访问已弃用的属性 __ proto __?为什么不直接做 Function.prototype.str = function () { ... }?
  • @JohnKurlak 那更好!我想我在写答案时并没有意识到这是可能的。
  • @NateFerrero - 很棒的答案,谢谢!添加了我自己的扩展作为单独的答案。
  • 在我的 Android 上,nexus 4,运行 5.0.1,这不再适用于 Chrome。出于某种原因,它正在删除空格和 cmets。我不知道这是否是一个设置,但它肯定是在客户端。任何解决方法的想法?
【解决方案5】:

根据您运行的 JS/JS 引擎的风格(SpiderMonkey、AS3),您可以简单地编写内联 XML,您可以在其中放置多行文本,例如 heredoc:

var xml = <xml>
    Here 
    is 
    some 
    multiline 
    text!
</xml>

console.log(xml.toXMLString())
console.log(xml.toString()) // just gets the content

【讨论】:

    【解决方案6】:

    ES6 Template Strings 具有heredoc 功能。

    您可以声明用反引号(` `)括起来的字符串,并且可以扩展为多行。

    var str = `This is my template string...
    and is working across lines`;
    

    您还可以在模板字符串中包含表达式。这些由美元符号和花括号 (${expression}) 表示。

    var js = "Java Script";
    var des = `Template strings can now be used in ${js} with lot of additional features`;
    
    console.log(des); //"Template strings can now be used in Java Script with lot of additional features"
    

    实际上还有更多功能,例如 Tagged Temple Strings 和 Raw Strings。请在

    找到文档

    https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/template_strings

    【讨论】:

      【解决方案7】:

      我觉得仅仅为@NateFerrero's answer 的扩展写一个单独的答案很糟糕,但我觉得编辑他的答案也不合适,所以如果这个答案对你有用,请点赞@NateFerrero。

      tl;dr——对于那些希望在 inside 他们的heredoc 中使用块 cmets 的人...

      我主要需要 Javascript heredocs 来存储一段 CSS,例如

      var css = heredoc(function() {/*
          /**
           * Nuke rounded corners.
           */
          body div {
              border-top-left-radius: 0 !important;
              border-top-right-radius: 0 !important;
              border-bottom-right-radius: 0 !important;
              border-bottom-left-radius: 0 !important;
          }
      */});
      

      然而,正如您所见,我喜欢评论我的 CSS,不幸的是(正如语法高亮所暗示的那样)第一个 */ 结束了整个评论,破坏了 heredoc。


      对于这个特定目的 (CSS),我的解决方法是添加

      .replace(/(\/\*[\s\S]*?\*) \//g, '$1/')
      

      到@NateFerrero 的heredoc 内的链;完整形式:

      function heredoc (f) {
          return f.toString().match(/\/\*\s*([\s\S]*?)\s*\*\//m)[1].replace(/(\/\*[\s\S]*?\*) \//g, '$1/');
      };
      

      并通过在 */ 之间为“内部”块 cmets 添加一个空格来使用它,如下所示:

      var css = heredoc(function() {/*
          /**
           * Nuke rounded corners.
           * /
          body div {
              border-top-left-radius: 0 !important;
              border-top-right-radius: 0 !important;
              border-bottom-right-radius: 0 !important;
              border-bottom-left-radius: 0 !important;
          }
      */});
      

      replace 只是找到/* ... * / 并删除空间以生成/* ... */,从而在调用之前保留heredoc。


      您当然可以使用完全删除 cmets

      .replace(/\/\*[\s\S]*?\* \//g, '')
      

      你也可以支持//cmets,如果你将它们添加到链中:

      .replace(/^\s*\/\/.*$/mg, '')
      

      此外,除了*/ 之间的单个空格之外,您还可以执行其他操作,例如-

          /**
           * Nuke rounded corners.
           *-/
      

      如果您只是适当地更新正则表达式:

      .replace(/(\/\*[\s\S]*?\*)-\//g, '$1/')
                                ^
      

      或者您可能想要任意数量的空格而不是单个空格?

      .replace(/(\/\*[\s\S]*?\*)\s+\//g, '$1/')
                                ^^^
      

      【讨论】:

      • 酷!这是我的方法的一个已知限制,我喜欢它:)
      • 不要死,但这可以通过自定义开始和结束 cmets 来简化:/*!$## [/*your code*/] ##$!*/,并使用正则表达式检查
      【解决方案8】:

      ES5 及更早版本

      (function(){/**
      some random
      multi line
      text here
      **/}).toString().slice(15,-5);
      

      ES6 及更高版本

      `some random
      multi line
      text here`
      

      结果

      some random
      multi line
      text here
      

      【讨论】:

      • 最佳简单答案
      • 老式的东西是一个非常残酷的黑客:/
      【解决方案9】:

      您可以使用CoffeeScript,这是一种编译为 JavaScript 的语言。代码一一编译成等价的JS,运行时没有解释。

      当然,它有heredocs :)

      【讨论】:

      • 正确答案是否定的。 CoffeeScript 和 EJS 可以用作建议。
      • CoffeeScript 是我遇到的大多数 JS 问题的正确答案。如果您编写的 JS 超过了微不足道的数量(并且您重视自己的时间和精力),那么您应该为自己使用它。
      • 我认为这是一个很好的答案,因为它提供了一种简单的方法来规避javascript中没有heredoc的情况。为我节省了很多时间。
      • 如果你只想要一大块 js,但又不想实际编写它:coffeescript.org 并使用“Try Coffeescript”按钮。
      • 这更像是一个答案,而不是评分最高的答案,基本上只是......“不”。我讨厌那种答案。
      【解决方案10】:

      正如其他人所说,ES6 模板字符串为您提供了传统 heredocs 提供的大部分内容。

      如果您想更进一步并使用标记的模板字符串,theredoc 是一个不错的实用函数,可让您执行此操作:

      if (yourCodeIsIndented) {
        console.log(theredoc`
          Theredoc will strip the
          same amount of indentation
          from each line.
      
            You can still indent
            further if you want.
      
          It will also chop off the
          whitespace-only first and
          last lines.
        `)
      }
      

      【讨论】:

        【解决方案11】:

        你可以使用 Sweet.js 宏来添加它,as created by Tim Disney in this post

        请注意,这种方法使用反引号作为字符串分隔符:

        let str = macro {
            case {_ $template } => {
                var temp = #{$template}[0];
                var tempString = temp.token.value.raw;
                letstx $newTemp = [makeValue(tempString, #{here})];
                return #{$newTemp}
            }
        }
        
        str `foo bar baz`
        

        【讨论】:

          【解决方案12】:

          如果你手头有一些 html 和 jQuery,并且字符串是有效的 HTML,这可能很有用:

          <div id="heredoc"><!--heredoc content
          with multiple lines, even 'quotes' or "double quotes",
          beware not to leave any tag open--></div>
          <script>
          var str = (function() {
             var div = jQuery('#heredoc');
             var str = div.html();
             str = str.replace(/^<\!--/, "").toString();
             str = str.replace(/-->$/, "").toString();
             return str;
          })();
          </script>
          

          如果文本之间有 cmets "",它也可以工作,但部分文本可能是可见的。 这是小提琴:https://jsfiddle.net/hr6ar152/1/

          【讨论】:

            【解决方案13】:
            // js heredoc - http://stackoverflow.com/a/32915549/466363
            // a function with comment with eval-able string, use it just like regular string
            
            function extractFuncCommentString(func,comments) {
              var matches = func.toString().match(/function\s*\(\)\s*\{\s*\/\*\!?\s*([\s\S]+?)\s*\*\/\s*\}/);
              if (!matches) return undefined;
              var str=matches[1];
            
               // i have made few flavors of comment removal add yours if you need something special, copy replacement lines from examples below, mix them
              if(comments===1 )
              {
               // keep comments, in order to keep comments  you need to convert /**/ to / * * / to be able to put them inside /**/ like /*    / * * /    */
               return (
                str
               .replace(/\/\s\*([\s\S]*?)\*\s\//g,"/*$1*/") //       change   / * text * /  to   /* text */ 
               )
              }
              else if(comments===2)
              {
               // keep comments and replace singleline comment to multiline comment
               return (
                str
               .replace(/\/\s\*([\s\S]*?)\*\s\//g,"/*$1*/") //       change   / * text * /  to   /* text */ 
               .replace(/\/\/(.*)/g,"/*$1*/")          //           change   //abc to  /*abc*/
               )
              }
              else if(comments===3)
              {
               // remove comments
               return (
                  str
                  .replace(/\/\s\*([\s\S]*?)\*\s\//g,"") //       match / * abc * /
                  .replace(/\/\/(.*)/g,"")             // match //abc
                 )
              }
              else if(comments===4)
              {
               // remove comments and trim and replace new lines with escape codes
               return (
                  str
                  .replace(/\/\s\*([\s\S]*?)\*\s\//g,"") //       match / * abc * /
                  .replace(/\/\/(.*)/g,"")             // match //abc
                  .trim() // after removing comments trim and:
                  .replace(/\n/g,'\\n').replace(/\r/g,'\\r') // replace new lines with escape codes. allows further eval() of the string, you put in the comment function: a quoted text but with new lines
                 )
              }
              else if(comments===5)
              {
               // keep comments comments and replace strings, might not suit when there are spaces or comments before and after quotes 
               // no comments allowed before quotes of the string
               return (
                  str
                  .replace(/\/\s\*([\s\S]*?)\*\s\//g,"/*$1*/") //       change   / * text * /  to   /* text */
                  .replace(/\/\/(.*)/g,"/*$1*/")          //           change   //abc to  /*abc*/
                  .trim() // trim space around quotes to not escape it and:
                  .replace(/\n/g,'\\n').replace(/\r/g,'\\r') // replace new lines with escape codes. allows further eval() of the string, you put in the comment function: a quoted text but with new lines
                 )
              }
              else 
              return str
            }
            

            例子

            var week=true,b=123;
            var q = eval(extractFuncCommentString(function(){/*!
            
            // this is a comment     
            
            
            'select 
            
            / * this
            is a multiline 
            comment * /
            
             a
            ,b  // this is a comment  
            ,c
            from `table`
            where b='+b+' and monthweek="'+(week?'w':'m')+'" 
            //+' where  a=124
            order by a asc
            '
            */},4));
            

            with cache: - 做一个简单的模板函数,并保存函数:(第二次工作很快)

            var myfunction_sql1;
            function myfunction(week,a){
            
            
                if(!myfunction_sql1) eval('myfunction_sql1=function(week,a){return ('+extractFuncCommentString(function(){/*!
            'select 
            
            / * this
            is a multiline 
            comment * /
            
             a
            ,b  // this is a comment  
            ,c
            from `table`
            where b='+b+' and monthweek="'+(week?'w':'m')+'" 
            //+' where  a=124
            order by a asc
            
            '*/},4)+')}');
                q=myfunction_sql1(week,a);
                console.log(q)
            }
            myfunction(true,1234)
            

            【讨论】:

            • FF 和 Chrome 的结果完全不同。
            • 有什么不同?刚刚在 Chrome 和 FF 中进行了测试,我得到了完全相同的结果。除了在 Chrome 中,如果您只输入 var 名称,Chrome 的控制台中没有换行符。但变量是一样的。可以使用 console.log() 打印换行符
            【解决方案14】:

            我发布这个版本是因为它避免了将正则表达式用于如此琐碎的事情。

            恕我直言,正则表达式是一种混淆,它是作为 perl 开发人员之间的恶作剧而创建的。社区的其他人认真对待他们,几十年后我们现在付出了代价。不要使用正则表达式,除了与遗留代码的向后兼容性。如今,没有任何借口可以编写人类无法立即阅读和理解的代码。正则表达式在各个层面都违反了这一原则。

            我还添加了一种将结果添加到当前页面的方法,而不是要求这样做。

            function pretty_css () {
            /*
                pre { color: blue; }
            
            */
            }
            function css_src (css_fn) {
               var css = css_fn.toString();
               css = css.substr(css.indexOf("/*")+2);
               return css.substr(0,css.lastIndexOf("*/")).trim();
            }
            
            function addCss(rule) {
              let css = document.createElement('style');
              css.type = 'text/css';
              if (css.styleSheet) css.styleSheet.cssText = rule; // Support for IE
              else css.appendChild(document.createTextNode(rule)); // Support for the rest
              document.getElementsByTagName("head")[0].appendChild(css);
            }
            
            addCss(css_src(pretty_css));
            
            document.querySelector("pre").innerHTML=css_src(pretty_css);
            &lt;pre&gt;&lt;/pre&gt;

            【讨论】:

              猜你喜欢
              • 2016-08-24
              • 2011-07-16
              • 2015-02-23
              • 2012-02-19
              • 2011-06-08
              • 2013-11-24
              • 2016-11-18
              • 2011-05-15
              • 2015-12-29
              相关资源
              最近更新 更多