رشته‌ها در ES 6
اندازه‌ی قلم متن
تخمین مدت زمان مطالعه‌ی مطلب: شش دقیقه

در بیشتر زبان‌های برنامه‌نویسی قابلیتی تحت عنوان String Interpolation وجود دارد. منظور، فرآیند جایگزین کردن مقادیر، با یکسری placeholder درون یک رشته است. در نسخه‌های قبلی جاوا اسکریپت محدودیت‌هایی در استفاده از رشته‌ها وجود داشت و امکان انجام این کار به صورت توکار مهیا نبود. یعنی برای پیاده‌سازی این قابلیت می‌توانستیم با تغییر prototype شیء String و یا روش‌های دیگری این‌حالت را پیاده‌سازی کنیم (+):

// First, checks if it isn't implemented yet.
if (!String.prototype.format) {
  String.prototype.format = function() {
    var args = arguments;
    return this.replace(/{(\d+)}/g, function(match, number) { 
      return typeof args[number] != 'undefined'
        ? args[number]
        : match
      ;
    });
  };
}
"Hello, {0}, I'm a simple {1}, Today is: {2}".format("World", "String", new Date());

// Output

"Hello, World, I'm a simple String, Today is: Tue Dec 29 2015 10:21:10 GMT+0330 (Iran Standard Time)"

اما در ES 6 با کمک قابلیتی تحت عنوان template string این محدودیت‌ها به طور قابل ملاحظه‌ایی کاهش پیدا کرده است. در واقع یک template string، یک رشته‌ی جاوا اسکریپتی است که به جای (" ") و یا (' ') درون دو کاراکتر (` `) یا به اصطلاح back-tick character محصور خواهد شد. این ویژگی در سناریوهای مختلفی کاریرد دارد. از این ویژگی می‌توانیم جهت الحاق رشته‌ها استفاده کنیم. به عنوان مثال می‌توانیم کد زیر را:

let category = "music";
let id = 2112;

let url = "http://apiserver/" + category + "/" + id;

با کمک template string به اینصورت بازنویسی کنیم:

let category = "music";
let id = 2112;

let url = `http://apiserver/${category}/${id}`;

و یا می‌توانیم مثال ابتدای مطلب را به اینصورت بازنویسی کنیم:

console.log(`Hello, ${"World"}, I'm a simple ${"String"}, Today is: ${new Date()}`);

همانطور که عنوان شد برای استفاده از این قابلیت باید رشته‌ی موردنظر را درون دو کاراکتر (` `) قرار دهیم. سپس درون این کاراکترها می‌توانیم literal text و همچنین یکسری placeholder جهت جایگزین کردن با مقادیر و عبارات موردنظر داشته باشیم. این placeholder‌ها نیز با استفاده از سینتکس { }$ قابل تعریف هستند.  لازم به ذکر است که عبارت موردنظرمان را باید درون دو علامت { } بنویسیم. مقادیر درون این دو علامت می‌توانند هر عبارت معتبر جاوا اسکریپتی باشند: 

let a = 5;
let b = 10;
console.log(`Fifteen is ${a + b} and\nnot ${2 * a + b}.`);
// "Fifteen is 15 and
// not 20."

در کد فوق متغیرهای a و b درون placeholder‌های مربوطه جایگزین خواهند شد. همانطور که مشاهده می‌کنید، این سینتکس نسبت به سینتکس + که برای الحاق رشته‌ها قبلاً مورد استفاده قرار می‌گرفت خیلی بهتر و خواناتر است.

به صورت خلاصه:

  • کد درون placeholder می‌تواند هر عبارت جاوا اسکریپتی باشد.
  • اگر مقدار درون placeholder یک رشته نباشد٬ توسط متد toString به رشته تبدیل خواهد شد.
  • اگر بخواهید درون template string از یک کاراکتر backtick استفاده کنید٬ می‌توانید به این صورت عمل کنید: 
`\``

// یا

"`"
در واقع می‌توانید توسط یک بک‌اسلش ار کارکترهای back tick و $ صرفنظر کنید.

  Multiline Strings 

console.log(`string text line 1
string text line 2`);
// "string text line 1
// string text line 2"

همانطور که مشاهده می‌کنید، template string از متن‌های چندخطی نیز به خوبی پشتیبانی می‌کند. به عنوان مثال اگر رشته‌ی فوق را درون گیومه می‌نوشتیم می‌بایستی از سینتکس + برای الحاق دو خط فوق استفاده می‌کردیم:

console.log("string text line 1\n"+
"string text line 2");
// "string text line 1
// string text line 2"

محدودیت‌های template strings
  • به صورت خودکار کارکترهای خاص را برای شما escape نمی‌کند (جهت جلوگیری از آسیب‌پذیری‌های XSS).
  • به صورت کامل از کتابخانه‌هایی جهت اعمال internationalization پشتیبانی نمی‌کند.
  • جایگزینی برای کتابخانه‌هایی مانند  Mustache و  Nunjucks نیست.
ES 6 قابلیت دیگری تحت عنوان tagged templates جهت رفع محدودیت‌های فوق در اختیارمان قرار می‌دهد. سینتکس آن نیز خیلی ساده است. کافی است قبل از کارکتر back-tick یک tag نوشته شود. قبل از توضیح این قابلیت مثال زیر را در نظر بگیرید:
var x = 1;
var y = 3;
var result = upper `${x} + ${y} is ${x+y}`;

console.log(result);

// Output
// 1 + 3 IS 4
همانطور که مشاهده می‌کنید متغیرهای x و y و همچنین مجموع آنها را درون رشته‌ی فوق قرار داده‌ایم. اما نکته‌ایی که در اینجا وجود دارد این است که مقدار خروجی دقیقاً معادل template نیست؛ زیرا در خروجی، is به صورت حروف بزرگ نمایش داده شده است. دلیل آن نیز این است که قبل از شروع کاراکتر back-tick، از یک تگ با نام upper استفاده کرده‌ایم. در واقع یک تگ چیزی بیشتر از یک تابع نیست که در ادامه پیاده‌سازی آن را مشاهده خواهید کرد:
let upper = function(strings, ...values){
  let result = "";
  for(var i = 0; i < strings.length; i++){
    result += strings[i];
    if(i < values.length){
      result += values[i];
    }
  }
  return result.toUpperCase();
};
تابع فوق دو پارامتر را از ورودی دریافت خواهد کرد: به اولین پارامتر parsed template string گفته می‌شود و مقدار آن متن parse شده درون کاراکتر‌های back-tick است. به پارامتر دوم نیز rest parameter گفته می‌شود که در واقع یک آرایه از مقادیر placeholder هایمان است. در نتیجه مقادیر این دو پارامتر به صورت زیر خواهد بود:
strings = ["", " + ", " is ", ""];
values  = [1, 3, 4];
درون تابع با مقادیر فوق می‌توانیم کارهای مختلفی را انجام دهیم. به عنوان مثال در اینجا ایجاد همان رشته؛ اما اینبار به صورت upper case.
در نتیجه با استفاده از این قابلیت می‌توانیم تگ‌های سفارشی زیادی را ایجاد کنیم. به عنوان مثال می‌توانیم تگی را ایجاد کنیم که تمپلیتی را دریافت کرده و آن را به HTML encoded تبدیل کند و در این‌حالت به ما در جلوگیری از حملات XSS و همچنین رفع محدویت‌هایی که در template strings داشتیم کمک خواهد کرد.

یک مثال عملی
می‌خواهیم یک tag template ایجاد کنیم که به انتهای اعداد درون یک تملپت، مقدار "تومان" را اضافه کرده و خود عدد را نیز به صورت سه رقم سه رقم جدا کند. می‌خواهیم رشته‌ی زیر همراه با مقادیر آن:
var name = "سیروان عفیفی";
var price = 150000;
var text = withToman `${name} با تشکر از خرید شما, مبلغ قابل پرداخت: ${price}`;
alert(text);
در خروجی اینچنین نمایش داده شود:

کدهای تگ withToman نیز به اینصورت میباشد:
function withToman(strings, ...values) {
  return strings.reduce( function (s, v, idx) {
    if(idx > 0) {
      if(typeof values[idx - 1] == "number") {
        s += `${values[idx - 1].toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")} تومان`
      }
      else {
        s += values[idx -1];
      }
    }
    return s + v;
  }, "");
}
همچنین در حالت پیشرفته‌تری می‌توان از این قابلیت جهت ایجاد یک DSL یا (Domain Specific Languages) ایده گرفت.