JavaScript의 문자열은 Python이나 Ruby와 같은 언어에서 기대할 수 있는 기능이 부족하여 제한적이었습니다. ES6 템플릿 문자열 (Chrome 41 이상에서 사용 가능)은 이를 근본적으로 변경합니다. 도메인별 언어 (DSL)로 문자열을 정의하는 방법을 도입하여 다음과 같은 이점을 제공합니다.
- 문자열 삽입
- 삽입된 표현식
- 해킹 없이 여러 줄 문자열
- 문자열 서식 지정
- 안전한 HTML 이스케이프, 현지화 등을 위한 문자열 태그 지정
오늘날 우리가 알고 있는 문자열에 또 다른 기능을 추가하는 대신 템플릿 문자열은 이러한 문제를 해결하는 완전히 다른 방법을 도입합니다.
문법
템플릿 문자열은 일반 문자열에서 사용하는 작은따옴표나 큰따옴표 대신 백틱 (``)을 사용합니다. 따라서 템플릿 문자열은 다음과 같이 작성할 수 있습니다.
var greeting = `Yo World!`;
지금까지 템플릿 문자열은 일반 문자열보다 나은 점이 없었습니다. 이를 바꿔 보겠습니다.
문자열 대체
이러한 기능의 첫 번째 실제 이점은 문자열 대체입니다. 치환을 사용하면 유효한 JavaScript 표현식 (예: 변수 추가)을 사용할 수 있으며 템플릿 리터럴 내에서 결과가 동일한 문자열의 일부로 출력됩니다.
템플릿 문자열에는 아래와 같이 ${ } 구문을 사용하여 문자열 대체용 자리표시자가 포함될 수 있습니다.
// Simple string substitution
var name = "Brendan";
console.log(`Yo, ${name}!`);
// => "Yo, Brendan!"
템플릿 문자열의 모든 문자열 대체는 JavaScript 표현식이므로 변수 이름보다 훨씬 많은 것을 대체할 수 있습니다. 예를 들어 아래에서는 표현식 삽입을 사용하여 읽기 쉬운 인라인 수학을 삽입할 수 있습니다.
var a = 10;
var b = 10;
console.log(`JavaScript first appeared ${a+b} years ago. Wow!`);
//=> JavaScript first appeared 20 years ago. Wow!
console.log(`The number of JS MVC frameworks is ${2 * (a + b)} and not ${10 * (a + b)}.`);
//=> The number of JS frameworks is 40 and not 200.
표현식 내의 함수에도 매우 유용합니다.
function fn() { return "I am a result. Rarr"; }
console.log(`foo ${fn()} bar`);
//=> foo I am a result. Rarr bar.
${}는 멤버 표현식과 메서드 호출을 비롯한 모든 종류의 표현식과 잘 작동합니다.
var user = {name: 'Caitlin Potter'};
console.log(`Thanks for getting this into V8, ${user.name.toUpperCase()}.`);
// => "Thanks for getting this into V8, CAITLIN POTTER";
// And another example
var thing = 'template strings';
console.log(`Say hello to ${thing}.`);
// => Say hello to template strings
문자열 내에 백틱이 필요한 경우 다음과 같이 백슬래시 문자 \를 사용하여 이스케이프할 수 있습니다.
var greeting = `\`Yo\` World!`;
여러 줄 문자열
JavaScript의 여러 줄 문자열에는 한동안 해키한 해결 방법이 필요했습니다. 현재 솔루션에서는 문자열이 단일 줄에 있거나 각 줄바꿈 앞에 \ (백슬래시)를 사용하여 여러 줄 문자열로 분할되어야 합니다. 예를 들면 다음과 같습니다.
var greeting = "Yo \
World";
이 방법은 대부분의 최신 JavaScript 엔진에서 잘 작동하지만 동작 자체는 여전히 약간의 해킹입니다. 문자열 연결을 사용하여 멀티라인 지원을 모방할 수도 있지만 이 역시 만족스럽지 않습니다.
var greeting = "Yo " +
"World";
템플릿 문자열은 여러 줄 문자열을 크게 단순화합니다. 필요한 곳에 줄바꿈을 포함하기만 하면 됩니다. 예를 들면 다음과 같습니다.
백틱 문법 내의 공백도 문자열의 일부로 간주됩니다.
console.log(`string text line 1
string text line 2`);
태그된 템플릿
지금까지 문자열 대체와 여러 줄 문자열을 만드는 데 템플릿 문자열을 사용하는 방법을 살펴봤습니다. 태그가 지정된 템플릿도 유용한 기능입니다. 태그가 지정된 템플릿은 템플릿 문자열 앞에 함수 이름을 배치하여 템플릿 문자열을 변환합니다. 예를 들면 다음과 같습니다.
fn`Hello ${you}! You're looking ${adjective} today!`
태그가 지정된 템플릿 문자열의 의미는 일반 문자열의 의미와 매우 다릅니다. 기본적으로 특수한 유형의 함수 호출입니다. 위의 코드는 다음과 같이 'desugar'됩니다.
fn(["Hello ", "! You're looking ", " today!"], you, adjective);
(n + 1)번째 인수는 문자열 배열의 n번째 항목과 (n + 1)번째 항목 사이에 발생하는 대체에 해당합니다. 이 기능은 다양한 용도로 사용할 수 있지만 가장 간단한 용도 중 하나는 삽입된 변수를 자동으로 이스케이프하는 것입니다.
예를 들어 다음과 같은 HTML 이스케이프 함수를 작성할 수 있습니다.
html`<p title="${title}">Hello ${you}!</p>`
적절한 변수가 대체되었지만 HTML에 안전하지 않은 모든 문자가 대체된 문자열을 반환합니다. 함께 해보겠습니다. HTML 이스케이프 함수는 사용자 이름과 댓글이라는 두 개의 인수를 사용합니다. 두 값 모두 HTML에 안전하지 않은 문자 (즉, ', ", <, >, &)를 포함할 수 있습니다. 예를 들어 사용자 이름이 'Domenic Denicola'이고 댓글이 '& is a fun tag'인 경우 다음과 같이 출력해야 합니다.
<b>Domenic Denicola says:</b> "& is a fun tag"
따라서 태그가 지정된 템플릿 솔루션은 다음과 같이 작성할 수 있습니다.
// HTML Escape helper utility
var util = (function () {
// Thanks to Andrea Giammarchi
var
reEscape = /[&<>'"]/g,
reUnescape = /&(?:amp|#38|lt|#60|gt|#62|apos|#39|quot|#34);/g,
oEscape = {
'&': '&',
'<': '<',
'>': '>',
"'": ''',
'"': '"'
},
oUnescape = {
'&': '&',
'&': '&',
'<': '<',
'<': '<',
'>': '>',
'>': '>',
''': "'",
''': "'",
'"': '"',
'"': '"'
},
fnEscape = function (m) {
return oEscape[m];
},
fnUnescape = function (m) {
return oUnescape[m];
},
replace = String.prototype.replace
;
return (Object.freeze || Object)({
escape: function escape(s) {
return replace.call(s, reEscape, fnEscape);
},
unescape: function unescape(s) {
return replace.call(s, reUnescape, fnUnescape);
}
});
}());
// Tagged template function
function html(pieces) {
var result = pieces[0];
var substitutions = [].slice.call(arguments, 1);
for (var i = 0; i < substitutions.length; ++i) {
result += util.escape(substitutions[i]) + pieces[i + 1];
}
return result;
}
var username = "Domenic Denicola";
var tag = "& is a fun tag";
console.log(html`<b>${username} says</b>: "${tag}"`);
//=> <b>Domenic Denicola says</b>: "& is a fun tag"
자동 이스케이프, 서식 지정, 현지화, 더 복잡한 대체 등도 사용할 수 있습니다.
// Contextual auto-escaping
qsa`.${className}`;
safehtml`<a href="${url}?q=${query}" onclick="alert('${message}')" style="color: ${color}">${message}</a>`;
// Localization and formatting
l10n`Hello ${name}; you are visitor number ${visitor}:n! You have ${money}:c in your account!`
// Embedded HTML/XML
jsx`<a href="${url}">${text}</a>` // becomes React.DOM.a({ href: url }, text)
// DSLs for code execution
var childProcess = sh`ps ax | grep ${pid}`;
요약
템플릿 문자열은 Chrome 41 베타 이상, IE 기술 미리보기, Firefox 35 이상, io.js에서 지원됩니다. 실제로 오늘 프로덕션에서 사용하려면 Traceur 및 6to5를 비롯한 주요 ES6 트랜스파일러에서 지원됩니다. 사용해 보려면 Chrome 샘플 저장소의 템플릿 문자열 샘플을 확인하세요. ES5의 ES6 동등 항목도 참고해 보세요. 이 문서에서는 오늘날 ES5를 사용하여 템플릿 문자열이 제공하는 일부 설탕을 구현하는 방법을 보여줍니다.
템플릿 문자열은 JavaScript에 많은 중요한 기능을 제공합니다. 여기에는 문자열 및 표현식 삽입, 여러 줄 문자열, 자체 DSL 생성 기능이 포함됩니다.
이러한 DSL을 작성하는 데 중요한 기능인 태그가 지정된 템플릿이 제공됩니다. 템플릿 문자열의 일부를 인수로 받으며, 문자열과 대체 항목을 사용하여 문자열의 최종 출력을 결정할 수 있습니다.