一.작용 및 구문
템플릿 문자열은 문자열의 삽입을 실현하는 데 사용되며, 플러스 기호 (+) 로 연결하는 것보다 편리하고 우아합니다
`${expr}` 구문은, 문자열 삽입 기능을 제공합니다
주의: 위의`(백쿼트, 키보드의 Esc 아래에 있습니다) 는 템플릿 문자열 구문의 일부이며, markdown 의 오류가 아닙니다
P.S.필자는 최초의 문제에 직면했습니다. 백쿼트와 markdown 구문이 충돌합니다. 2 개의 선택이 있습니다. markdown 특성의 다중 백쿼트를 코드 구분 문자로 사용하는 (2 개의 연속 백쿼트로 코드를 감싸지만, 필자가 사용하는 markdown 플러그인은 이 드문 구문을 지원하지 않음), 또는 code 태그를 사용하는 것. 예를 들어 위의 markdown 소스 코드는<code>\`${expr}\`</code> 입니다
예를 들어:
function req(user, action) {
// if !isValid
error(`user ${user} failed to do action ${action}`);
}
function error(str) {
console.log(str);
}
// test
req('Sam', 'login'); // user Sam failed to do action login
二.특징
###1.expr 은 임의의 합법 js 식으로 좋으며, 네스트도 서포트
변수, 리터럴, 함수 호출 등을 포함하지만, 플로 제어 (분기/루프) 는 서포트하지 않으므로, 템플릿 문자열은 템플릿 엔진을 대체할 수 없습니다
예를 들어:
// 不支持分支/循环
// console.log(`${if (2 > 1) {str}}`); // Uncaught SyntaxError: Unexpected token if
// console.log(`${for (; false;) {}}`); // Uncaught SyntaxError: Unexpected token for
var outer = 'outer';
var inner = 'inner';
var str = `
\$\{
${
outer // 变量
+ // + 拼接
`\$\{
${inner} // 插值
\}`
}
\}
`;
var h5 = document.querySelector('#h5');
var pre = document.querySelector('#pre');
h5.innerHTML = str;
pre.innerHTML = str;
표시 결과는 다음과 같습니다:
// #h5
${ outer${ inner // 插值 } }
// #pre
${
outer${
inner // 插值
}
}
###3.복수 행으로 분할하여 기술 가능
다만 주석 (단행/다행) 은 문자열 전체에 작용하거나, 또는 결과 문자열 내에 리터럴로서 나타날 가능성이 있습니다. 템플릿 문자열 중의 모든 스페이스, 개행, 인덴트는, 생성된 문자열 중에 그대로 출력됩니다 (pre 는 다른 요소와 다릅니다). 구체적으로는 위의 예를 참조
###4.특수 문자는 이스케이프 필요
3 개의 특수 문자[`${](정규 표현식 형식) 는 이스케이프가 필요합니다. 구체적으로는 위의 예를 참조
P.S.우중괄호는 이스케이프 불필요하지만, 물론 이스케이프해도 틀리지 않습니다. 그러나 위의 3 つ는필수로 이스케이프할 필요가 있습니다
###5.자동 처리 없음
안전하지 않은 태그를 자동 필터링하지 않으며, 특수 문자를 자동 이스케이프하지도 않습니다. xss 공격도 방지할 필요가 있습니다. 태그 템플릿 (tagged templates) 을 제공하지만, 그다지 편리하지 않습니다
예를 들어:
// xss 攻击
var userInput = '<a href="" onclick="alert(\'xss attack\');">领取奖励</a>';
var input = document.querySelector('#input');
input.innerHTML = `用户输入:${userInput}`;
위의 코드는 링크를 생성하며, 클릭하면 "xss attack" 을 alert 합니다. 태그 템플릿을 통해 템플릿 문자열을 커스텀 처리할 수 있습니다. 예를 들어 안전하지 않은 문자를 필터링:
// 定义模板标签
function myFilter(templateData) {
var aStr = templateData; // 被${}插值分割后的字符串数组
var aRaw = templateData.raw; // 未经转义的原字符串(\n)
var aVar = Array.prototype.slice.call(arguments, 1); // 插值变量数组
console.log(aStr);
console.log(aRaw);
console.log(aVar);
// filter vars
aVar.forEach(function(item, index, arr) {
arr[index] = item.replace(/(<[^>]*>)/i, '');
});
var res = '';
var i = 0;
aStr.forEach(function(item) {
res += item;
if (aVar[i]) {
res += aVar[i++];
}
});
return res;
}
// 使用标签模板
var safeInput = document.querySelector('#safe_input');
safeInput.innerHTML = myFilter`用户输入:\n${userInput}`;
// 等价于
// safeInput.innerHTML = myFilter(['用户输入:'], userInput);
태그는 템플릿 문자열 앞에 나타나며, 간략화된 함수 호출 의 일종입니다. 템플릿 태그는 콜백 함수에 유사하며, 파라미터 templateData 의 형식은 확정되어 있으며, 파라미터에서 데이터를 꺼내어, 처리 완료 후에 반환할 뿐입니다
그러나 템플릿 태그를 정의하는 것은 아직 번거롭게 느껴지지만, 이는 매우 매력적인 특성으로, 강력한 문자열 처리 라이브러리 (특수 문자의 이스케이프, i18n, 문자수 통계 등) 를 예감시킵니다
###6.유연성
태그 템플릿의 반환 값은 문자열일 필요는 없으며, 임의의 값 으로構いません. 이는 단순히 강력한「문자열」처리 라이브러리가 나타날 뿐만 아니라, 모든 라이브러리가 이 형식으로 완벽하게 JS 내에묻어 수 있는 것을 의미하며, 특히 쉐이더 언어와 같은 현재 JS 내에서 형식이 그다지 우호적이지 않은 것……다른 언어에서 매력적인 특성이 나타난 후, 완벽하게 JS 에 이식할 수 있으며, 더욱이借此로 고유의 언어를 실장할 수도 있습니다 (템플릿 태그의 함수 본체가 인터프리터입니다)
태그 템플릿은 큰 유연성을 가져오며, 커스텀 태그를 사용하여 정규 표현식, DOM 트리, 이미지, promises 를 대표하는 비동기 프로세스 전체, JS 데이터 구조, GL 쉐이더 등을 작성할 수 있습니다……
참고 자료 중의 원문을 인용:
标签模板以开放的姿态欢迎库设计者们来创建强有力领域特定语言。这些语言可能看起来不像 JS,但是它们仍可以无缝嵌入到 JS 中并与 JS 的其它语言特性智能交互。我不知道这一特性将会带领们走向何方,但它蕴藏着无限的可能性,这令我感到异常兴奋!
三.정리
템플릿 문자열은 일견 구문 설탕이지만,実は扉를 열었으며, JS 가 오픈한 자세로 미래를 맞이하는 것을 나타내고 있습니다
[선배들이 5 년 전에 논의한 yield](/articles/javascript 实现 yield/) 를 기억하고 있습니까? 당시 그들은 이러한 특성을 얼마나 바랐을까요. 이 문제를 논의한初衷은 JS 가 C# 의 yield 특성을 획득하는 것을 바랐기 때문이 아닙니까?
참고 자료
- 《ES6 in Depth》:InfoQ 中文站提供的免费电子书
아직 댓글이 없습니다