ก่อนหน้านี้สตริงใน JavaScript เคยถูกจำกัด ทำให้ขาดความสามารถที่อาจเกิดจากภาษาอย่างเช่น Python หรือ Ruby โดยพื้นฐานแล้ว สตริงเทมเพลต ES6 (พร้อมใช้งานใน Chrome 41 ขึ้นไป) พวกเขาแนะนำวิธีกำหนดสตริงด้วยภาษาเฉพาะโดเมน (DSL) ซึ่งให้ผลดีกว่าดังนี้
- การประมาณค่าในช่วงสตริง
- นิพจน์ที่ฝัง
- สตริงหลายบรรทัดที่ไม่มีการแฮ็ก
- การจัดรูปแบบสตริง
- การติดแท็กสตริงเพื่อการ Escape HTML ที่ปลอดภัย การแปลให้เหมาะกับท้องถิ่น และอื่นๆ
แทนที่จะใส่คุณลักษณะอื่นลงในสตริงตามที่เรารู้จักในปัจจุบัน สตริงเทมเพลตนำเสนอวิธีใหม่ในการแก้ปัญหาเหล่านี้อย่างสิ้นเชิง
ไวยากรณ์
สตริงเทมเพลตใช้เครื่องหมายแบ็กกราวด์ (``) แทนที่จะเป็นเครื่องหมายคำพูดเดี่ยวหรือเครื่องหมายคำพูดคู่ที่เราใช้กับสตริงปกติ สตริงเทมเพลตอาจเขียนได้ดังนี้
var greeting = `Yo World!`;
จนถึงตอนนี้ สตริงเทมเพลตยังไม่ได้ให้อะไรเรามากกว่าสตริงปกติ มาเปลี่ยนแปลงกัน
การแทนสตริง
ประโยชน์ที่แท้จริงประการแรกคือการแทนที่สตริง การแทนจะทำให้เราสามารถใช้นิพจน์ JavaScript ที่ถูกต้องใดๆ (เช่น การเพิ่มตัวแปร) และภายในเทมเพลต Literal นี้ ผลลัพธ์ที่ได้จะออกมาเป็นส่วนหนึ่งของสตริงเดียวกัน
สตริงเทมเพลตมีตัวยึดตำแหน่งสำหรับการแทนที่สตริงได้โดยใช้ไวยากรณ์ ${ }
ดังที่แสดงด้านล่าง
// 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!`
ความหมายของสตริงเทมเพลตที่ติดแท็กแตกต่างจากสตริงปกติอย่างมาก ตามหลักแล้ว สารเหล่านี้คือการเรียกใช้ฟังก์ชันประเภทพิเศษ ซึ่งก็คือ "น้ำตาล" ข้างต้นเป็น
fn(["Hello ", "! You're looking ", " today!"], you, adjective);
สังเกตว่าอาร์กิวเมนต์ (n + 1) สัมพันธ์กับการแทนที่เกิดขึ้นระหว่างรายการที่ n และ (n + 1) ในอาร์เรย์สตริงอย่างไร ซึ่งมีประโยชน์สำหรับทุกๆ อย่าง แต่วิธีการหนึ่งที่ตรงไปตรงมาที่สุดคือการหลบเลี่ยงตัวแปรที่แทรกเข้ามาโดยอัตโนมัติ
ตัวอย่างเช่น คุณสามารถเขียนฟังก์ชันการ Escape HTML ในลักษณะนี้..
html`<p title="${title}">Hello ${you}!</p>`
แสดงผลสตริงที่มีตัวแปรที่เหมาะสมซึ่งแทรกเข้ามา แต่แทนที่อักขระ HTML ที่ไม่ปลอดภัยทั้งหมด มาเริ่มกันเลย ฟังก์ชันการ Escape HTML ของเราจะใช้อาร์กิวเมนต์ 2 ตัว คือ ชื่อผู้ใช้และความคิดเห็น ผลิตภัณฑ์ทั้งสองอาจมีอักขระที่ไม่ปลอดภัยของ HTML (ได้แก่ ', ", <, > และ &) ตัวอย่างเช่น หากชื่อผู้ใช้คือ "Domenic Denicola" และความคิดเห็นคือ "& is a business 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"
การใช้งานที่เป็นไปได้อื่นๆ ได้แก่ การ Escape อัตโนมัติ การจัดรูปแบบ การแปล และโดยทั่วไปจะใช้แทนที่ซับซ้อนกว่านั้น
// 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 Tech Preview, Firefox 35+ และ io.js พูดง่ายๆ ก็คือหากต้องการนำไปใช้งานจริงในปัจจุบัน อุปกรณ์นี้รองรับ Transpiler ของ ES6 หลักๆ แล้ว รวมถึง Traceur และ 6to5 ด้วย หากต้องการลองใช้ โปรดดูตัวอย่างสตริงเทมเพลตในที่เก็บตัวอย่างของ Chrome นอกจากนี้คุณอาจสนใจดูค่าเทียบเท่า ES6 ใน ES5 ซึ่งสาธิตวิธีบรรลุเป้าหมายสตริงเทมเพลตการเพิ่มค่าน้ำตาลที่ได้จากการใช้ ES5 ในปัจจุบัน
สตริงเทมเพลตนำความสามารถที่สำคัญหลายอย่างมาสู่ JavaScript ซึ่งรวมถึงวิธีที่ดีขึ้นในการประมาณค่าในช่วงสตริงและนิพจน์ สตริงหลายบรรทัด และความสามารถในการสร้าง DSL ของคุณเอง
ฟีเจอร์ที่สำคัญที่สุดอย่างหนึ่งจากผู้นำนี้คือเทมเพลตที่ติดแท็ก ซึ่งเป็นฟีเจอร์สำคัญในการจัดทำ DSL ดังกล่าว โดยจะรับส่วนต่างๆ ของสตริงเทมเพลตเป็นอาร์กิวเมนต์ จากนั้นคุณจึงตัดสินใจได้ว่าจะใช้สตริงและการแทนที่เพื่อระบุผลลัพธ์สุดท้ายของสตริงอย่างไร