javascript - Hvordan kan jeg tildele en flerliniers strengliteral til en variabel?


Hvordan konverterer jeg denne Ruby-koden med en flerlinjers streng til JavaScript?

text = <<"HERE"
This
Is
A
Multiline
String
HERE

Svar #1

ECMAScript 6 (ES6) introduserer en ny type literal, nemlig template-literals. De har mange funksjoner, blant annet variabelinterpolasjon, men viktigst for dette spørsmålet, de kan være flerliniers.

Et malstrenger er avgrenset av bakgrunnstegn:

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

(Merk: Jeg anbefaler ikke å bruke HTML i tekststrenger)

Nettleserstøtte er OK, men du kan bruke transpilekere for å være mer kompatibel.


Original ES5-svar:

JavaScript har ikke en heredoc-syntaks. Du kan derimot unnslippe det bokstavelige linjeskiftet, noe som kommer nær:

"foo \
bar"

Svar #2

ES6

Som det første svaret nevner, med ES6/Babel kan du nå lage flerlinsestrenger enkelt ved å bruke bakoverapostrofer:

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

Interpolering av variabler er en populær ny funksjon som følger med strenger avgrenset med back-ticks:

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

Dette blir bare transpileret ned til sammenkjedning:

user.name + ' liked your post about strings'

ES5

Googles JavaScript-stilveiledning anbefaler å bruke strengsammenkobling i stedet for å unnslippe linjeskift:

Ikke gjør dette:

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.';

Whitespaces på begynnelsen av hver linje kan ikke trygt fjernes under kompilering; whitespaces etter skråstreken vil føre til vanskelige feil; og selv om de fleste skriptmotorer støtter dette, er det ikke en del av ECMAScript.

Bruk strengsammenkobling i stedet:

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.';

Svar #3

Mønsteret text=<<"HERE" This Is A Multiline String HERE er ikke tilgjengelig i JavaScript (jeg husker at jeg brukte det mye i mine gode gamle Perl-dager).

For å holde oversikt over komplekse eller lange flerlingsstrenger bruker jeg noen ganger et array-mønster:

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

Eller mønsteret Anonymous allerede viste (escape linjeskift), som kan være en stygg blokk i koden din:

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

Her er en annen rar, men fungerende, 'triks'1:

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

Ekstern redigering: jsfiddle

ES20xx støtter å spre strenger over flere linjer ved bruk av malstrenger:

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 Merk: dette vil gå tapt etter minifisering/obfuskering av koden din

Svar #4

Du kan ha flerlina strenger i ren JavaScript.

Denne metoden er basert på serialisering av funksjoner, som er definert til å være implementasjonsavhengig. Den fungerer i de fleste nettlesere (se nedenfor), men det er ingen garanti for at den vil fungere i fremtiden, så ikke stol på den.

Ved å bruke følgende funksjon:

function hereDoc(f) {
  return f.toString().
      replace(/^[^\/]+\/\*!?/, '').
      replace(/\*\/[^\/]+$/, '');
}

Du kan ha here-dokumenter slik:

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

Metoden har blitt testet med hell i følgende nettlesere (ikke nevnt=ikke testet):

  • IE 4 - 10
  • Opera 9.50 - 12 (ikke i 9-)
  • Safari 4 - 6 (ikke i 3-)
  • Chrome 1 - 45
  • Firefox 17 - 21 (ikke i 16-)
  • Rekonq 0.7.0 - 0.8.0
  • Støttes ikke i Konqueror 4.7.4

Vær forsiktig med minifiseringsverktøyet ditt, da. Det har en tendens til å fjerne kommentarer. For YUI-kompressoren vil en kommentar som starter med /*! (som den jeg brukte) bli beholdt.

Jeg tror en ekte løsning ville være å bruke CoffeeScript.

ES6 OPPDATERING: Du kan bruke backtick i stedet for å lage en funksjon med en kommentar og kjøre toString på kommentaren. Regex-en må oppdateres for å bare fjerne mellomrom. Du kan også ha en strengprototype-metode for å gjøre dette:

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

Noen bør skrive denne .removeIndentation strengmetoden... ;)

Svar #5

Du kan gjøre dette...

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

Svar #6

Jeg kom opp med denne veldig nødløsningen for en flerliniers streng. Siden det å konvertere en funksjon til en streng også returnerer alle kommentarer inne i funksjonen, kan du bruke kommentarene som strengen din ved å bruke en flerliniers kommentar /**/. Du må bare trimme endene, og du har strengen din.

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)

Svar #7

Jeg er overrasket over at jeg ikke så dette, fordi det fungerer overalt jeg har testet det og er veldig nyttig for f.eks. maler:

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

Vet noen om et miljø der det finnes HTML, men det fungerer ikke?

Svar #8

Jeg løste dette ved å legge ut en div, gjøre den skjult, og kalle div-id-en med jQuery når jeg trengte den.

f.eks.

<div id="UniqueID" style="display:none;">
     Strings
     On
     Multiple
     Lines
     Here
</div>

Så når jeg trenger å få strengen, bruker jeg bare følgende jQuery:

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

Som returnerer teksten min på flere linjer. Hvis jeg kaller

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

Jeg får:

Svar #9

Det finnes flere måter å oppnå dette på

1. Skråstrek-konkatenasjon

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

2. vanlig sammenkobling

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

3. Sammenkobling av matriser

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

Når det gjelder ytelse, er Slash-konkatenasjon (den første) den raskeste.

Referer denne testcasen for mer informasjon om ytelsen

Oppdatering:

Med ES2015 kan vi dra nytte av funksjonen med Template-strenger. Med den trenger vi bare å bruke back-ticks for å lage flersidige strenger

Eksempel :

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

Svar #10

Bruke skript-tagger:

  • legg til en <script>...</script>-blokk som inneholder din flerlags tekst i head-taggen;
  • få din flerlags tekst som den er... (vær oppmerksom på tekstkoding: 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>
    

Svar #11

En enkel måte å skrive ut flerlinsestrenger i JavaScript på er ved å bruke malbokstaver (template strings) som angis med backticks (` `). Du kan også bruke variabler inne i en malstreng, for eksempel (`name is ${value}`).

Du kan også

const value = `multiline`
const text = `This is a
${value}
string in js`;
console.log(text);

Svar #12

Jeg liker denne syntaksen og innrykkingen:

string = 'my long string...\n'
       + 'continue here\n'
       + 'and here.';

(men kan egentlig ikke betraktes som en flerlijnjersstreng)

Svar #13

Denne koden leveres kun for informasjon.

Dette har blitt testet i Firefox 19 og Chrome 24 på Mac.

DEMO

var new_comment; /*<<<EOF
    <li class="photobooth-comment">
       <span class="username">
          <a href="#">You</a>:
       </span>
       <span class="comment-text">
          $text
       </span>
       @<span class="comment-time">
          2d
       </span> ago
    </li>
EOF*/
// note the script tag here is hardcoded as the FIRST tag
new_comment=document.currentScript.innerHTML.split("EOF")[1];
document.querySelector("ul").innerHTML=new_comment.replace('$text','This is a dynamically created text');
<ul></ul>

Svar #14

Det finnes et bibliotek som gjør det vakkert:

https://github.com/sindresorhus/multiline

Før

var str = '' +
'<!doctype html>' +
'<html>' +
'   <body>' +
'       <h1>❤ unicorns</h1>' +
'   </body>' +
'</html>' +
'';

Etter

var str = multiline(function(){/*
<!doctype html>
<html>
    <body>
        <h1>❤ unicorns</h1>
    </body>
</html>
*/});

Svar #15

Jeg fant mange overkompliserte svar her.

De to beste svarene etter min mening var:

En

 let str = `Multiline string.
            foo.
            bar.`

som til slutt logger:

Multiline string.
           foo.
           bar.

To

let str = `Multiline string.
foo.
bar.`

Det logger det riktig, men det ser stygt ut i skriptfilen hvis str er nestet inne i funksjoner, objekter osv…:

Multiline string.
foo.
bar.

Mitt veldig enkle svar med regex som logger str korrekt:

let str = `Multiline string.
           foo.
           bar.`.replace(/\n +/g, '\n');

Vennligst merk at det ikke er den perfekte løsningen, men det fungerer hvis du er sikker på at etter den nye linjen (\n) vil det komme minst ett mellomrom (+ betyr minst én forekomst). Det vil også fungere med * (null eller flere).

Du kan være mer eksplisitt og bruke {n,}, som betyr minst n forekomster.

Svar #16

Den tilsvarende i JavaScript er:

var text = `
This
Is
A
Multiline
String
`;

Her er spesifikasjonen. Se nettleserstøtte nederst på denne siden. Her er noen eksempler også.

Svar #17

Eksakt

Ruby produserer: "This\nIs\nA\nMultiline\nString\n"—den følgende JavaScript-koden produserer nøyaktig samme streng.

text = `This
Is
A
Multiline
String
`

// TEST
console.log(JSON.stringify(text));
console.log(text);

Dette er en forbedring av Lonnies beste svar, fordi linjeskift-tegnene i hans svar ikke er nøyaktig på de samme plassene som i Ruby-utdataene.

Svar #18

For å oppsummere, har jeg prøvd to tilnærminger som er listet her i bruker JavaScript-programmering (Opera 11.01):

  • denne fungerte ikke: Hvordan kan jeg tilordne en flerliniers strengliteral til en variabel?
  • dette fungerte ganske bra. Jeg har også funnet ut hvordan jeg kan få det til å se bra ut i Notepad++ kildevisning: Hvordan kan jeg tilordne en flerliniers strengliteral til en variabel?

Så jeg anbefaler arbeidsmetoden for Opera-brukere som bruker JavaScript. I motsetning til det forfatteren sa:

Det fungerer ikke i Firefox eller Opera; bare i IE, Chrome og Safari.

Det fungerer i Opera 11. I det minste i bruker-JavaScript-skript. Synd at jeg ikke kan kommentere individuelle svar eller stemme opp svaret, jeg ville gjort det umiddelbart. Hvis mulig, vær så snill noen med høyere privilegier gjør det for meg.

Svar #19

Dette fungerer i Internet Explorer, Safari, Google Chrome og Firefox:

<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js"></script>
<div class="crazy_idea" thorn_in_my_side='<table  border="0">
                        <tr>
                            <td ><span class="mlayouttablecellsdynamic">PACKAGE price $65.00</span></td>
                        </tr>
                    </table>'></div>
<script type="text/javascript">
    alert($(".crazy_idea").attr("thorn_in_my_side"));
</script>

Svar #20

Dette er mitt tillegg til Luks svar.

Den forventer en kommentar i formen /*! enhver multiline-kommentar */ hvor symbolet ! brukes for å forhindre at den blir fjernet ved minifisering (i det minste for YUI-kompressoren):

Function.prototype.extractComment = function() {
    var startComment = "/*!";
    var endComment = "*/";
    var str = this.toString();

    var start = str.indexOf(startComment);
    var end = str.lastIndexOf(endComment);

    return str.slice(start + startComment.length, -(str.length - end));
};

Eksempel :

var tmpl = function() { /*!
 <div class="navbar-collapse collapse">
    <ul class="nav navbar-nav">
    </ul>
 </div>
*/}.extractComment();

Relaterte artikler