在JavaScript中创建多行字符串

3420

我有以下的 Ruby 代码。我想将这段代码转换成 JavaScript。请问在 JavaScript 中等价的代码是什么?

text = <<"HERE"
This
Is
A
Multiline
String
HERE
43个回答

4430

更新:

ECMAScript 6 (ES6) 引入了一种新类型的字面量,即 模板字面量。它们具有许多特性,包括变量插值等,但最重要的是,它们可以是多行的。

模板字面量由 反引号 包围:

var html = `
  <div>
    <span>Some HTML here</span>
  </div>
`;

(注意:我不主张在字符串中使用HTML)

浏览器支持良好, 但您可以使用转换器来提高兼容性。


原始ES5答案:

Javascript没有here-document语法。 但是,您可以转义文字中的换行符,这个方法比较接近:

"foo \
bar"

281
警告:一些浏览器会在续行处插入换行符,而另一些则不会。 - staticsan
45
据看,Visual Studio 2010 对这个语法似乎也感到困惑。 - jcollum
63
在《ECMA-262第5版》第7.8.4节中指定了“行续字符(LineContinuation)”,其规定为:“字符串文字中不能出现行终止字符,除非作为行续字符的一部分以生成空字符序列。使行终止字符成为字符串文字的字符串值的正确方法是使用转义序列,如\n或\u000A。” - some
23
我不明白为什么你要这样做,因为浏览器对此处理并不一致。在多行中使用"line1\n" + "line2"的方式可读性已经足够,而且您可以获得一致的结果。 - SamStephens
23
浏览器支持还好,但不支持IE11 - 不太行 - Tom Andraszek
显示剩余20条评论

1540

ES6更新:

正如第一个回答提到的那样,使用ES6/Babel,您现在可以通过使用反引号来创建多行字符串:

const htmlString = `Say hello to 
multi-line
strings!`;

插值变量是使用反引号定界字符串的一种流行新功能:

const htmlString = `${user.name} liked your post about strings`;

这只是转换为连接:

user.name + ' liked your post about strings'

原始的ES5答案:

Google's JavaScript style guide recommends to use string concatenation instead of escaping newlines:

Do not do this:

var myString = 'A rather long string of English text, an error message \
                actually that just keeps going and going -- an error \
                message to make the Energizer bunny blush (right through \
                those Schwarzenegger shades)! Where was I? Oh yes, \
                you\'ve got an error and all the extraneous whitespace is \
                just gravy.  Have a nice day.';

The whitespace at the beginning of each line can't be safely stripped at compile time; whitespace after the slash will result in tricky errors; and while most script engines support this, it is not part of ECMAScript.

Use string concatenation instead:

var myString = 'A rather long string of English text, an error message ' +
               'actually that just keeps going and going -- an error ' +
               'message to make the Energizer bunny blush (right through ' +
               'those Schwarzenegger shades)! Where was I? Oh yes, ' +
               'you\'ve got an error and all the extraneous whitespace is ' +
               'just gravy.  Have a nice day.';

28
我不明白谷歌的建议。除了旧版本的浏览器外,所有浏览器都支持反斜杠后跟换行符的方法,并且出于向后兼容的考虑,将来也会继续支持。唯一需要避免使用这种方法的情况是如果你需要确保每行仅添加一个换行符(或没有换行符)的情况(请参见我对被接受答案的评论)。 - Matt Browne
8
请注意,模板字符串不支持IE11、Firefox 31、Chrome 35或Safari 7。详情请见http://kangax.github.io/compat-table/es6/。 - EricP
46
谷歌的建议已经由他们本人记录,按照原因的重要性排序:(1)每行开头的空格[在示例中,您不希望字符串中有该空格,但它使代码看起来更美观](2)斜杠后的空格会导致棘手的错误[如果您以\ 而不是\\结束一行,则很难注意到],以及(3)虽然大多数脚本引擎都支持此功能,但它不是ECMAScript的一部分[即为什么使用非标准功能?]请记住,这是一个样式指南,其目的是使代码易于阅读、维护和调试,而不仅仅是“能运行”。 - ShreevatsaR
3
多年过去,字符串连接仍然是处理这个问题最好、最安全、最符合标准的方式,这真是太棒了。模板字面量(上面的答案)在 IE 中无法使用,而转义行只会使事情变得混乱,你很快就会后悔。 - Tiago Duarte
3
发现老版本的安卓系统不支持反引号,因此如果你在使用webView的安卓应用程序中使用反引号,将导致你的应用程序无法运行!请注意。 - Michael Fever
显示剩余5条评论

737

在js中并没有可用的模式text = <<"HERE" This Is A Multiline String HERE(我记得在我以前使用Perl的旧日子里它经常被使用)。

为了更好地处理复杂或长的多行字符串,我有时会使用数组模式:

var myString = 
   ['<div id="someId">',
    'some content<br />',
    '<a href="#someRef">someRefTxt</a>',
    '</div>'
   ].join('\n');

或者像anonymous展示的模式一样(转义换行符),这可能会成为代码中一个丑陋的块:

    var myString = 
       '<div id="someId"> \
some content<br /> \
<a href="#someRef">someRefTxt</a> \
</div>';

这里有另一个奇怪但可行的“技巧”1:

var myString = (function () {/*
   <div id="someId">
     some content<br />
     <a href="#someRef">someRefTxt</a>
    </div>        
*/}).toString().match(/[^]*\/\*([^]*)\*\/\}$/)[1];

外部编辑:jsfiddle

ES20xx支持使用模板字符串跨多行拼接字符串:

let str = `This is a text
    with multiple lines.
    Escapes are interpreted,
    \n is a newline.`;
let str = String.raw`This is a text
    with multiple lines.
    Escapes are not interpreted,
    \n is not a newline.`;

1 注意:这将在压缩/混淆代码后丢失


39
大多数情况下,请不要使用数组模式,因为它比简单的字符串连接方式更慢。 - BMiner
86
数组模式更易读,对应用程序性能的损失通常可以忽略不计。正如性能测试所显示的那样,即使是IE7每秒也可以执行数万个操作。 - Benjamin Atkin
23
赞一个优雅的替代方案,它不仅在所有浏览器中以相同的方式运行,而且还具有未来兼容性。 - Pavel
28
@KooiInc,你的测试从已经创建好的数组开始,这会使结果产生偏差。如果你添加数组的初始化,直接连接字符串会更快 http://jsperf.com/string-concat-without-sringbuilder/7。参考https://dev59.com/_HVD5IYBdhLWcg3wNYxZ#4717855。对于新行的技巧,可能可以使用,但它确实比应该做的更多的工作。 - Ruan Mendes
12
@BMiner:1)“过早优化是万恶之源”- Donald Knuth,2)'可读性'取决于观察者的角度 - user2418182
显示剩余27条评论

371

在纯JavaScript中,您可以使用多行字符串。

该方法基于函数的序列化,这被定义为依赖于实现的。它在大多数浏览器中都能工作(请参阅下文),但不能保证它将来仍将起作用,所以不要依赖它。

使用以下函数:

function hereDoc(f) {
  return f.toString().
      replace(/^[^\/]+\/\*!?/, '').
      replace(/\*\/[^\/]+$/, '');
}
您可以像这样使用here-documents:

您可以像这样使用here-documents:

var tennysonQuote = hereDoc(function() {/*!
  Theirs not to make reply,
  Theirs not to reason why,
  Theirs but to do and die
*/});

该方法已在以下浏览器中成功测试(未提及 = 未测试):

  • IE 4 - 10
  • Opera 9.50 - 12(不包括9-)
  • Safari 4 - 6(不包括3-)
  • Chrome 1 - 45
  • Firefox 17 - 21(不包括16-
  • Rekonq 0.7.0 - 0.8.0
  • 不支持Konqueror 4.7.4

但要小心你的代码压缩器。它往往会删除注释。对于YUI 压缩器,以 /*! 开头的注释(就像我用的那个)将被保留。

我认为一个真正的解决方案是使用CoffeeScript

ES6 更新:您可以使用反引号代替创建带有注释并运行 toString 的函数。正则表达式需要更新以仅剥离空格。您还可以拥有一个字符串原型方法来完成此操作:

let foo = `
  bar loves cake
  baz loves beer
  beer loves people
`.removeIndentation()

应该有人写一个 .removeIndentation 字符串方法... ;)


284
什么?创建和反编译一个函数,以便将多行注释变成多行字符串?现在那真的是很丑陋。 - fforw
5
这个链接:http://jsfiddle.net/fqpwf/ 在Chrome 13 和IE8/9中可用,但在FF6中不行。我不想这么说,但我喜欢它,如果每个浏览器都有这个故障,并且成为了一个特性(以便它不会消失),那我就会使用它。 翻译:此链接在Chrome 13和IE8/9中正常工作,但在FF6中无法使用。作者表示虽然不想这么说,他仍喜欢这个功能,如果这个问题变成每个浏览器的意料之中并保留下来,他会继续使用它。 - Jason Kleban
3
要让它有意义,它必须在规范中;或者被广泛使用,以至于浏览器制造商不想删除这个“偶然”的功能。感谢你的实验...尝试一些CoffeeScript吧。 - Jordão
2
a.toString().substring(15, a.toString().length-4) 也可以使用,并且不需要扫描整个字符串(尽管它很可能会扫描,并且计算使其又成为了一次扫描。哎呀,没办法)。 - Lodewijk
3
非常方便。我正在用它进行(茉莉)单元测试,但在生产代码中避免使用它。 - Jason
显示剩余19条评论

223

你可以这样做...

var string = 'This is\n' +
'a multiline\n' + 
'string';

第一个例子非常好而且简单。比起使用反斜杠作为转义字符和多行字符,这种方法要好得多,因为我不确定浏览器如何处理反斜杠。 - Matt K
CDATA代码(E4X)已过时,并且即将在Firefox中停止工作。 - Brock Adams
e4x.js 将是一个良好的具有未来性的解决方案。 - Paul Sweatte

186

我想出了一种非常简单的多行字符串的方法。由于将函数转换为字符串还会返回函数内部的任何注释,因此您可以使用多行注释作为字符串。您只需要修剪两端并得到您的字符串。

var myString = function(){/*
    This is some
    awesome multi-lined
    string using a comment 
    inside a function 
    returned as a string.
    Enjoy the jimmy rigged code.
*/}.toString().slice(14,-3)

alert(myString)

50
这绝对是令人恐惧的。我喜欢它。(尽管您可能需要进行正则表达式匹配,因为我不确定toString()中的空格有多精确。) - Kevin Cox
2
这个解决方案似乎在Firefox中不起作用,也许这是浏览器的安全特性?编辑:算了,它只是在Firefox 16版本中不起作用。 - Bill Software Engineer
59
请注意不要使用会去除注释的压缩工具... :D - jondavidjohn
9
这就是为什么我们不能拥有好东西。 - Danilo M. Oliveira
8
在 JavaScript 领域里,你可以做一些奇怪的事情。不过说实话,你永远不应该使用这种方法。 - Luke
显示剩余5条评论

94

我很惊讶我没有看到这个,因为它在我测试的所有地方都有效,并且对于例如模板非常有用:

<script type="bogus" id="multi">
    My
    multiline
    string
</script>
<script>
    alert($('#multi').html());
</script>

有没有人知道一个环境,其中包含HTML,但它不起作用?


25
任何你不想把字符串分别放在远离的脚本元素中的地方。 - Lodewijk
10
一个合理的反对意见!它并不完美。但对于模板来说,这种分离不仅是可以接受的,甚至可能是被鼓励的。 - Peter V. Mørch
2
我更喜欢将超过80/120个字符的所有内容拆分成多行,我担心这不仅仅是模板。现在我更喜欢使用“line1”+“line2”的语法。它也是最快的(尽管对于非常大的文本可能会有竞争)。这是一个不错的技巧。 - Lodewijk
29
实际上,这是HTML而不是Javascript :-/ - CpILL
6
然而,在 JavaScript 中获取多行字符串的任务可以通过以下方式完成。 - Davi Fiamenghi
显示剩余5条评论

60
我通过输出一个div(隐藏)并在需要时通过jQuery调用该div的ID来解决了这个问题。 例如:
<div id="UniqueID" style="display:none;">
     Strings
     On
     Multiple
     Lines
     Here
</div>

那么当我需要获取该字符串时,只需使用以下jQuery:

$('#UniqueID').html();

这种方法可以让我的文本跨越多行显示。如果我调用

alert($('#UniqueID').html());
我理解您需要进行翻译的内容如下:

我得到的结果是:

在此输入图片描述

请确认以上翻译是否符合您的要求。

4
谢谢你!这是我找到的唯一解决方案,因为我的问题涉及未知字符串,可能包含任意组合的单引号和双引号,并直接插入代码而没有预编码的机会。 (它来自一个模板语言,它创建JS - 仍然来自可信源而不是表单提交,所以它不是完全疯狂的)。 - octern
这对我完成工作很有帮助,但它不能解决将多行字符串值分配给JavaScript变量的问题。 - Venkat
4
如果这个字符串是HTML格式,该怎么办? - Dan Dascalescu
4
$('#UniqueID').content() - mplungjan
1
@Pacerier 我所阅读的来自Google和其他网站的资料都表明,现在Google确实会索引display:none的内容,这很可能是由于JavaScript样式的前端变得越来越流行。(例如,一个带有隐藏/显示功能的FAQ页面。)但你需要小心,因为Google表示,如果隐藏的内容似乎是为了人为地提高你的SEO排名而设计的,他们可以惩罚你。 - Gavin
显示剩余4条评论

34

有多种方法可以实现这一点。

1. 斜杠连接

  var MultiLine=  '1\
    2\
    3\
    4\
    5\
    6\
    7\
    8\
    9';

2. 普通连接

var MultiLine = '1'
+'2'
+'3'
+'4'
+'5';

3. 数组连接

var MultiLine = [
'1',
'2',
'3',
'4',
'5'
].join('');

就性能而言,斜杠连接(第一个)是最快的。

有关性能的更多详细信息,请参见此测试案例

更新:

使用ES2015版本,我们可以利用其模板字符串功能。使用它,我们只需使用反引号创建多行字符串。

例如:

 `<h1>{{title}}</h1>
  <h2>{{hero.name}} details!</h2>
  <div><label>id: </label>{{hero.id}}</div>
  <div><label>name: </label>{{hero.name}}</div>
  `

11
我认为你刚刚以更简洁的方式复述了过去五年页面上已经存在的内容。 - RandomInsano
拼接字符串时,不会将行首的空格包含在内吗? - f.khantsis

32

使用脚本标签:

  • 将包含多行文本的 <script>...</script> 代码块添加到 head 标签中;
  • 获取您的多行文本原样...(注意文本编码:UTF-8、ASCII)

<script>

    // pure javascript
    var text = document.getElementById("mySoapMessage").innerHTML ;

    // using JQuery's document ready for safety
    $(document).ready(function() {

        var text = $("#mySoapMessage").html(); 

    });

</script>

<script id="mySoapMessage" type="text/plain">

    <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:typ="...">
       <soapenv:Header/>
       <soapenv:Body>
          <typ:getConvocadosElement>
             ...
          </typ:getConvocadosElement>
       </soapenv:Body>
    </soapenv:Envelope>

    <!-- this comment will be present on your string -->
    //uh-oh, javascript comments...  SOAP request will fail 


</script>

我认为这个策略很干净且被低估了。jsrender使用了它。 - xdhmoore
我正在使用innerText而不是innerHTML,但是如何确保空格被保留? - David Nouls
此外,如果您正在使用ajax查询,则可以尝试更改头文件xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");。我记得除了在JS中拼写错误的注释之外,没有遇到其他问题。空格不是问题。 - jpfreire

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接