ES6 템플릿 리터럴 대 연결 문자열


84

Ecma-Script-6에 대한 다음 코드가 있습니다. template literals

let person = {name: 'John Smith'};   
let tpl = `My name is ${person.name}.`;    
let MyVar="My name is "+ person.name+".";

console.log("template literal= "+tpl);  
console.log("my variable = "+MyVar);

출력은 다음과 같습니다.

template literal= My name is John Smith.
my variable = My name is John Smith.

이것은 바이올린입니다. 나는 정확한 차이점을 검색했지만 찾을 수 없었습니다. 제 질문은이 두 진술의 차이점은 무엇입니까?

  let tpl = `My name is ${person.name}.`;    

  let MyVar = "My name is "+ person.name+".";

이미 여기에 문자열을 MyVar연결할 person.name수 있으므로 템플릿 리터럴을 사용하는 시나리오는 무엇입니까?


8
이것은 다른 언어에서 흔히 볼 수있는 기능입니다. 깨끗해 보이며 여러 줄입니다.
elclanrs

5
"차이"가 무엇을 의미하는지 잘 모르겠 tpl === MyVar습니까? 유일한 차이점은 생성 된 구문입니다. 템플릿은 문자열 연결과 달리 자동 이스케이프와 같은 작업에 사용할 수있는 태그 기능도 제공합니다.
Bergi

기본적으로 문자열 보간과 문자열 연결의 차이점이 무엇인지 묻습니다.
Damjan Pavlica

답변:


104

`Hello ${person.name}`질문의 예와 같이 자리 표시 자 (예 :)와 함께 템플릿 리터럴 만 사용 하는 경우 결과는 문자열을 연결하는 것과 동일합니다. 주관적으로는 특히 여러 줄 문자열 또는 둘 모두를 포함하는 문자열을 위해, 더 나은 외모와 읽기 쉽게 '그리고 "당신은 더 이상 그 문자를 이스케이프 할 필요가 없기 때문에.

가독성은 훌륭한 기능이지만 템플릿에서 가장 흥미로운 점은 태그지정된 템플릿 리터럴입니다 .

let person = {name: 'John Smith'}; 
let tag = (strArr, name) => strArr[0] + name.toUpperCase() + strArr[1];  
tag `My name is ${person.name}!` // Output: My name is JOHN SMITH!

이 예제의 세 번째 줄에서는 이름 tag이 지정된 함수 가 호출됩니다. 템플릿 문자열의 내용은 tag함수 의 인수에서 액세스 할 수있는 여러 변수로 분할됩니다 . 리터럴 섹션 (이 예에서는 strArr[0]is My name is의 값과 strArr[1]is 의 값 !) 및 대체 ( John Smith). 템플릿 리터럴은 tag함수가 반환 하는 모든 항목으로 평가됩니다 .

ECMAScript를 위키 자동 탈출 또는 입력 또는 제이션을 코딩 같이 나열 몇 가지 가능한 사용 사례. msg다음과 같이 리터럴 부분을 조회 My name is하고 현재 로케일의 언어 (예 : 독일어) 로의 번역으로 대체하는 이름 이 지정된 태그 함수를 만들 수 있습니다 .

console.log(msg`My name is ${person.name}.`) // Output: Mein Name ist John Smith.

태그 함수가 반환하는 값은 문자열이 아니어도됩니다. $다음 예제 와 같이 문자열을 평가하고이를 쿼리 선택기로 사용하여 DOM 노드 모음을 반환 하는 태그 함수를 만들 수 있습니다 .

$`a.${className}[href=~'//${domain}/']`

2
좋은! $ {person.message}와 같은 다른 템플릿 리터럴이 있다면 함께 번역됩니까?
Rigotti

1
@Rigotti 그것은 msg기능 의 구현에 달려 있습니다. 확실히 대체 값을 번역 할 수도 있습니다.
kapex

@Beat 전체 ecmascript.org 사이트가 다운 된 것 같습니다. 어차피 위키를 포기할 계획이있는 것 같아서 보관 된 버전으로 링크를 업데이트했습니다.
kapex

나는 $를 실행하려고 a.${className}[href=~'//${domain}/']크롬 콘솔 (과 전에 설정 className=''하고 domain=''우리가 콘솔에서 오류가 jsfiddle에, / (다른을 한게에 :하지만 난 DOM 노드하지만 문자열의 배열을하지 않는 jsfiddle.net/d1fkta76 "catch되지 않은 오류 ReferenceError : $는 "정의되지 않은 - 왜?
카밀 Kiełczewski

2
@AniketSuryavanshi 다음은 템플릿 문자열과 연결 성능의 비교입니다. stackoverflow.com/a/29083467/897024 몇 년 전에는 템플릿 문자열이 더 느 렸지만 지금은 연결보다 조금 더 빠른 것 같습니다.
kapex

16

ES6`백틱을 구분 기호로 사용하여 새로운 유형의 문자열 리터럴이 나타납니다 . 이러한 리터럴을 사용하면 기본 문자열 보간 표현식이 포함 된 다음 자동으로 구문 분석되고 평가됩니다.

let actor = {name: 'RajiniKanth', age: 68};

let oldWayStr = "<p>My name is " + actor.name + ",</p>\n" +
  "<p>I am " + actor.age + " old</p>\n";

let newWayHtmlStr =
 `<p>My name is ${actor.name},</p>
  <p>I am ${actor.age} old</p>`;

console.log(oldWayStr);
console.log(newWayHtmlStr);

보시다시피, 문자열 리터럴로 해석되는 일련의 문자 주위에 ..``를 사용했지만 형식의 모든 표현식은 ${..}즉시 인라인으로 구문 분석되고 평가됩니다.

보간 된 문자열 리터럴의 정말 좋은 이점 중 하나는 여러 줄로 나눌 수 있다는 것입니다.

var Actor = {"name" : "RajiniKanth"};

var text =
`Now is the time for all good men like ${Actor.name}
to come to the aid of their
country!`;
console.log( text );
// Now is the time for all good men
// to come to the aid of their
// country!

보간 된 식

함수 호출, 인라인 함수 표현식 호출 및 기타 !를 포함하여 모든 유효한 표현식이 ${..}보간 된 문자열 내부 에 나타날 수 있습니다 .lit‐ eralinterpo‐ lated string literals

function upper(s) {
 return s.toUpperCase();
}
var who = "reader"
var text =
`A very ${upper( "warm" )} welcome
to all of you ${upper( `${who}s` )}!`;
console.log( text );
// A very WARM welcome
// to all of you READERS!

여기에서 내부 $ {who} s ''보간 된 문자열 리터럴은 "s"who + "s"가 아닌 who 변수를 문자열 과 결합 할 때 우리에게 약간 더 편리했습니다 . 또한 메모를 유지하는 것은 보간 된 문자열 리터럴이 lexically scoped표시되는 위치 dynamically scoped이며 어떤 식으로도 표시되지 않습니다 .

function foo(str) {
 var name = "foo";
 console.log( str );
}
function bar() {
 var name = "bar";
 foo( `Hello from ${name}!` );
}
var name = "global";
bar(); // "Hello from bar!"

template literalHTML에를 사용하는 것은 성가심을 줄임으로써 확실히 더 읽기 쉽습니다.

평범한 옛날 방식 :

'<div class="' + className + '">' +
  '<p>' + content + '</p>' +
  '<a href="' + link + '">Let\'s go</a>'
'</div>';

와 함께 ES6:

`<div class="${className}">
  <p>${content}</p>
  <a href="${link}">Let's go</a>
</div>`
  • 문자열은 여러 줄에 걸쳐있을 수 있습니다.
  • 인용 문자를 이스케이프 할 필요가 없습니다.
  • ' ">'와 같은 그룹화를 피할 수 있습니다.
  • 더하기 연산자를 사용할 필요가 없습니다.

태그가 지정된 템플릿 리터럴

또한 template문자열에 태그를 지정할 수 있습니다 . template문자열에 태그가 지정되면 literals및 대체가 결과 값을 반환하는 함수에 전달됩니다.

function myTaggedLiteral(strings) {
  console.log(strings);
}

myTaggedLiteral`test`; //["test"]

function myTaggedLiteral(strings,value,value2) {
  console.log(strings,value, value2);
}
let someText = 'Neat';
myTaggedLiteral`test ${someText} ${2 + 3}`;
// ["test ", " ", ""]
// "Neat"
// 5

우리는 spread여기 연산자 여러 값을 전달할 수 있습니다. 첫 번째 인수 (문자열이라고 함)는 모든 일반 문자열 (보간 된 표현식 사이의 항목)의 배열입니다.

그런 다음 모든 후속 인수를를 사용하여 값이라는 배열로 수집합니다. ... gather/rest operator물론 위에서했던 것처럼 strings 매개 변수 다음에 개별 명명 된 매개 변수로 남겨 둘 수도 있습니다 (value1, value2 etc).

function myTaggedLiteral(strings,...values) {
  console.log(strings);
  console.log(values);    
}

let someText = 'Neat';
myTaggedLiteral`test ${someText} ${2 + 3}`;
// ["test ", " ", ""]
// ["Neat", 5]

argument(s)문자열 리터럴 검색된 이미 평가 보간 수식의 결과 값이 우리의 배열로되어 모였다. A tagged string literal는 보간이 평가 된 후 최종 문자열 값이 컴파일되기 전의 처리 단계와 같으므로 리터럴에서 문자열 생성을 더 잘 제어 할 수 있습니다. .NET Framework를 생성하는 예를 살펴 보겠습니다 re-usable templates.

const Actor = {
  name: "RajiniKanth",
  store: "Landmark"
}

const ActorTemplate = templater`<article>
  <h3>${'name'} is a Actor</h3>
  <p>You can find his movies at ${'store'}.</p>

</article>`;

function templater(strings, ...keys) {
  return function(data) {
  let temp = strings.slice();
  keys.forEach((key, i) => {
  temp[i] = temp[i] + data[key];
  });
  return temp.join('');
  }
};

const myTemplate = ActorTemplate(Actor);
console.log(myTemplate);

원시 문자열

우리의 태그 기능이라는 첫 번째 인수의 우리받을 strings입니다 array. 그러나 추가 데이터 비트가 포함되어 있습니다. 모든 문자열의 처리되지 않은 원시 버전입니다. 다음 .raw과 같이 속성을 사용하여 이러한 원시 문자열 값에 액세스 할 수 있습니다 .

function showraw(strings, ...values) {
 console.log( strings );
 console.log( strings.raw );
}
showraw`Hello\nWorld`;

보시다시피 raw, 문자열 의 버전은 이스케이프 된 \ n 시퀀스를 유지하는 반면, 처리 된 버전의 문자열은 이스케이프되지 않은 실제 줄 바꿈처럼 처리합니다. ES6문자열 리터럴 태그로 사용할 수있는 내장 함수가 함께 제공됩니다 : String.raw(..). 단순히의 원시 버전을 통과합니다 strings.

console.log( `Hello\nWorld` );
/* "Hello
World" */

console.log( String.raw`Hello\nWorld` );
// "Hello\nWorld"

4

주석에서 언급했듯이 훨씬 깔끔하고 다른 언어의 공통 기능입니다. 또 다른 좋은 점은 줄 바꿈으로 문자열을 작성할 때 매우 유용합니다.

let person = {name: 'John Smith', age: 24, greeting: 'Cool!' };

let usualHtmlStr = "<p>My name is " + person.name + ",</p>\n" +
                   "<p>I am " + person.age + " old</p>\n" +
                   "<strong>\"" + person.greeting +"\" is what I usually say</strong>";


let newHtmlStr = 
 `<p>My name is ${person.name},</p>
  <p>I am ${person.age} old</p>
  <p>"${person.greeting}" is what I usually say</strong>`;


console.log(usualHtmlStr);
console.log(newHtmlStr);

문자열과 리터럴에 줄 바꿈을 사용하는 데 큰 차이가 있는지 이해하지 못합니다. 이 es6fiddle.net/i3vj1ldl을 확인하십시오 . 문자는 줄 바꿈 대신 공간을두고
나임 샤이 크에게

1
와, 큰 차이라고 말하지 않았어요. 리터럴 줄 바꿈은 구문 설탕 일뿐입니다. 가독성을위한 것입니다.
Rigotti

하지만 여전히 좋은 차이점을 지적했습니다. (어떤이있는 경우!)하지만 답변을 수락하기 전에, 나는 어떤 큰 차이를 보여줍니다 더 나은 답변을 좀 더 시간을 기다리는 :
나임 샤이 크에게

2
@NaeemShaikh 정말 죄송하지만 문자 줄 바꿈은 실제로 작동합니다. ES6Fiddle은 테스트하는 끔찍한 방법이라는 것을 알았습니다. 내 대답을 편집하겠습니다.
Rigotti

2

내 대답은 질문을 직접적으로 다루지는 않습니다. 배열 조인을 위해 템플릿 리터럴을 사용하는 한 가지 단점을 지적하는 것이 흥미로울 수 있다고 생각했습니다.

내가 가지고 있다고 가정하자

let patient1 = {firstName: "John", lastName: "Smith"};
let patient2 = {firstName: "Dwayne", lastName: "Johnson", middleName: "'The Rock'"};

따라서 일부 환자는 middleName을 갖고 다른 환자는 그렇지 않습니다.

환자의 전체 이름을 나타내는 문자열을 원한다면

let patientName = `${patient1.firstName} ${patient1.middleName} ${patient1.lastName}`;

그러면 "John undefined Smith"가됩니다.

그러나 내가 그랬다면

let patientName = [patient1.firstName, patient1.middleName,  patient1.lastName].join(" ");

그러면 이것은 "John Smith"가됩니다.

편집하다

General_Twyckenham은 ""에 대한 조인이 "John"과 "Smith"사이에 추가 공백을 생성 할 것이라고 지적했습니다.

이 문제를 해결하려면 조인 전에 잘못된 값을 제거하는 필터를 사용할 수 있습니다. [patient1.firstName, patient1.middleName, patient1.lastName].filter(el => el).join(" ");


2
실제로는 정확하지 않습니다. join버전은 추가 공간이있는 John Smith를 제공합니다 . 상상할 수 있듯이 이것은 종종 바람직하지 않습니다. 이에 대한 수정은 다음 map과 같이 사용하는 것입니다.[patient1.firstName, patient1.middleName, patient1.lastName].map(el => el).join(" ");
General_Twyckenham

@General_Twyckenham aah 나는 당신의 요점을 봅니다. 잘 잡았습니다. 또한 여분의 공간을 제거하려면 맵이 아닌 필터 여야합니다. 내 대답을 수정하겠습니다. 감사합니다.
Dhruv Prakash

아, 네, filter제가 의미하는 기능이었습니다.
General_Twyckenham

그리고이 논의에 따르면 문자열 연결이 배열 연결보다 빠릅니다. stackoverflow.com/questions/7299010/…
마이클 할리
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.