بازگشت به دوره

کار با رشته ها و آشنایی با Template Literals

پیش از این با متغیرهای رشته‌ای و نحوه‌ی تعریف آنها آشنا شدیم. در این بخش قصد داریم با جزئیات بیشتری در رابطه با رشته‌ها صحبت کنیم.

در بخش قبلی با مفهوم Wrapper Object آشنا شدیم و دیدیم که هر نوع داده‌ی اولیه‌ای به صورت خودکار در یک شئ به نام Wrapper Object قرار می‌گیرد. این شئ بسته به نوع داده‌ی اولیه متفاوت است و دارای متدها و خاصیت‌هایی متناسب با نوع داده است. شیئی که به عنوان Wrapper Object برای داده‌های رشته‌ای به کار برده می‌شود، String نام دارد که دارای تعدادی متد و خاصیت است که در ادامه به بررسی آنها می‌پردازیم.

 

متدها و خاصیت‌های رشته‌ها

هر متغیر رشته‌ای، خاصیتی به نام length دارد که مقدار آن همیشه برابر با طول رشته (تعداد کاراکترهای رشته) است. برای دسترسی به خاصیت‌های یک شئ نیز مانند متدها باید از کاراکتر نقطه استفاده کنیم. اما در این حالت نیازی به پرانتز نیست. قطعه کد زیر نحوه‌ی استفاده از این خاصیت را نشان می‌دهد.


let str = "Hello World!";
str.length;
← 12
str = "JavaScript";
str.length;
← 10

توجه کنید که کاراکتر فاصله نیز محاسبه می‌شود. لذا طول رشته‌ی "Hello World!" برابر با ۱۲ کاراکتر است. همچنین برای دسترسی به خاصیت‌های یک شئ می‌توانیم از روش دیگری استفاده کنیم که کاربرد کمتری دارد. اما در شرایط خاص این روش می‌تواند مفید باشد. نحوه‌ی استفاده از این روش را در قطعه کد زیر می‌بینید.


let str = "Hello World!";
str['length'];
← 12

این روش به ندرت مورد استفاده قرار می‌گیرد و کاربرد آن زمانی است که نام خاصیت مورد نظر، یک شناسه‌ی معتبر نباشد. چنین حالتی نیز معمولاً زمانی رخ می‌دهد که شئ مورد نظر در جاوا اسکریپت تولید نشده باشد و از منبع دیگری (معمولاً به صورت Ajax و با قالب JSON) دریافت شده باشد. مثلاً فرض کنید نام یک خاصیت از یک شئ "last name" باشد. با توجه به وجود فاصله در این نام، از نظر جاوا اسکریپت این نام یک شناسه‌ی معتبر نیست. لذا از کاراکتر نقطه نمی‌توان برای دسترسی به این خاصیت استفاده کرد و تنها راه دسترسی به آن، استفاده از روش فوق است.

با استفاده از متدهای toUpperCase و toLowerCase می‌توان تمام کاراکترهای یک رشته را به ترتیب به حروف بزرگ و حروف کوچک تبدیل کرد. مثال‌هایی از کاربرد این متدها را در کد زیر می‌بینید.


let str = "Hello World!";
str.toUpperCase();
← "HELLO WORLD!"
str.toLowerCase();
← "hello world!"
str;
← "Hello World!"

توجه کنید که هیچ یک از این متدها تغییری در مقدار اولیه‌ی متغیر ایجاد نمی‌کنند. بلکه یک رشته‌ی جدید را تولید کرده و بازمی‌گردانند. لذا در دستور آخر کد فوق می‌بینید که مقدار متغیر str بدون تغییر مانده است.

با استفاده از متد charAt می‌توان به یک کاراکتر خاص از رشته، با استفاده از اندیس آن دست یافت. توجه کنید که در جاوا اسکریپت (و بیشتر زبان‌های برنامه‌نویسی) اندیس‌ها از صفر شروع می‌شوند. در نتیجه اندیس 1، به دومین کاراکتر از یک رشته اشاره می‌کند. قطعه کد زیر نحوه‌ی استفاده از این متد را نشان می‌دهد.


let str = "Hello World!";
str.charAt(1);
← "e"
str.charAt(6);
← "W"

با استفاده از متد indexOf هم می‌توانید اندیس اولین محل وقوع یک کاراکتر یا رشته را، در رشته‌ای دیگر جستجو کنید. در صورتی که کاراکتر یا رشته‌ی مورد جستجو در رشته‌ی اصلی وجود داشته باشد اندیس محل وقوع آن، و در غیر این صورت مقدار "1-" بازگردانده می‌شود.


let str = "Hello, welcome to JavaScript!";
str.indexOf('o');
← 4
str.indexOf('to');
← 15
str.indexOf('Java');
← 18
str.indexOf('java');
← -1
str.indexOf('HTML');
← -1

در حالت پیش‌فرض، جستجو از اولین کاراکتر، یعنی اندیس صفر شروع می‌شود. اما در صورت نیاز می‌توان با ارسال یک ورودی دیگر به متد indexOf، محل شروع جستجو را تغییر داد. به قطعه کد زیر توجه کنید.


let str = "Hello, welcome to JavaScript!";
str.indexOf('o');
← 4
str.indexOf('o' , 5);
← 11
str.indexOf('o' , 13);
← 16

با استفاده از متد lastIndexOf هم می‌توان آخرین محل وقوع یک کاراکتر یا رشته را جستجو کرد. این متد نیز در صورت عدم موفقیت مقدار "1-" را برمی‌گرداند. قطعه کد زیر نحوه‌ی عملکرد این متد را نشان می‌دهد.


let str = "Hello, welcome to JavaScript!";
str.lastIndexOf('o');
← 16
str.lastIndexOf('JavaScript');
← 18
str.lastIndexOf('o' , 10);
← 4
str.lastIndexOf('css');
← -1

توجه کنید که در این متد، جستجو از انتهای رشته به ابتدای آن انجام می‌شود. در نتیجه اگر عددی را به عنوان محل شروع جستجو مشخص کنید، جستجو از آن محل به سمت ابتدای رشته انجام می‌شود.

در صورتی که محل وقوع رشته‌ی مورد جستجو اهمیتی نداشته باشد. و فقط بررسی وجود و یا عدم وجود، هدف اصلی باشد. می‌توانیم از متد includes استفاده کنیم. این متد در صورت وجود زیر رشته در رشته‌ی اصلی، مقدار true و در غیر این صورت مقدار false را برمی‌گرداند. همچنین توجه کنید که این متد در استاندارد ES7 به ECMAScript اضافه شده است.


let str = "Hello, welcome to JavaScript!";
str.includes('welcome');
← true
str.includes('JavaScript');
← true
str.includes('javascript');
← false

برای تشخیص اینکه آیا یک رشته با یک کاراکتر یا زیر رشته‌ی خاص شروع می‌شود یا خیر، می‌توان از متد startsWith استفاده کرد. همچنین متد endsWith هم برای بررسی پایان یافتن یک رشته با یک کاراکتر یا زیر رشته‌ی خاص به کار می‌رود. قطعه کد زیر عملکرد این متدها را نمایش می‌دهد.


let str = "Hello, welcome to JavaScript!";
str.startsWith('welcome');
← false
str.startsWith('Hello');
← true
str.endsWith('JavaScript');
← false
str.endsWith('!');
← true

به منظور الحاق رشته‌ها به یکدیگر و ایجاد رشته‌های بزرگتر می‌توان از دو روش مختلف استفاده کرد. روش اول استفاده از متد concat است و روش دوم استفاده از عملگر "+" که در بین برنامه‌نویسان جاوا اسکریپت مرسوم‌تر است. هر دو روش در قطعه کد زیر نشان داده شده‌اند.


let str1 = "JavaScript" , str2 = "Hello";
str2.concat(' World!');
← "Hello World!"
str1.concat(' ' , 'is my' , ' ' , 'favorite language');
← "JavaScript is my favorite language"
str1 + ' is my ' + 'favorite ' + 'language';
← "JavaScript is my favorite language"
str2 + ' ' + 'Wo' + 'rld!';
← "Hello World!"

توجه کنید که هم در متد concat و هم در عملگر "+"، هیچ محدودیتی در تعداد رشته‌های الحاق شونده وجود ندارد و هر تعداد رشته را به این شکل می‌توان به یکدیگر متصل کرد.

متد دیگری که کاربرد زیادی در تعامل با رشته‌ها دارد، متد substring است. با استفاده از این متد می‌توان بخشی از یک رشته را استخراج کرد. یا به بیان دیگر با استفاده از این متد می‌توان یک زیر رشته از رشته‌ی اصلی را انتخاب کرد. این متد می‌تواند دو ورودی دریافت کند که ورودی اول اجباری و ورودی دوم اختیاری است. ورودی اول اندیس شروع زیر رشته، و ورودی دوم اندیس اولین کاراکتر بعد از زیر رشته را مشخص می‌کند. در صورت استفاده نکردن از ورودی دوم، از اندیس مشخص شده در ورودی اول تا پایان رشته انتخاب می‌شود. قطعه کد زیر نمونه‌هایی از کاربرد این متد را نشان می‌دهد.


let str = "Hello, welcome to JavaScript!";
str.substring(3);
← "lo, welcome to JavaScript!"
str.substring(3 , 10);
← "lo, wel"

آخرین متدی که در این قسمت معرفی می‌شود، متد repeat است. این متد یک رشته را به تعداد دفعات لازم تکرار می‌کند. قطعه کد زیر کاربرد این متد را به خوبی نشان می‌دهد.


let str1 = "JavaScript" , str2 = "Hello";
str1.repeat(2);
← "JavaScriptJavaScript"
str2.repeat(3);
← "HelloHelloHello"

در بخش قبلی اشاره شد که برای استفاده از متدهای شئ Wrapper Object، نیازی به تعریف یک متغیر نیست و می‌توان از داده‌های لیترال (Literal) یا لفظی برای این منظور استفاده کرد. لذا تمام متدهای معرفی شده در این قسمت نیز به این شکل قابل استفاده هستند. چند نمونه از این نوع استفاده از متدهای فوق و خاصیت length را در قطعه کد زیر مشاهده می‌کنید.


'JavaScript'.repeat(2);
← "JavaScriptJavaScript"
'Hello'.concat(' World!');
← "Hello World!"
'Hello World'.charAt(4);
← "o"
'Hello World'.length;
← 11
شئ String دارای چندین متد دیگر نیز می‌باشد که در زمان نیاز معرفی خواهند شد. لیست کامل این متدها را اینجا می‌توانید مشاهده کنید.  

تعریف رشته‌ها با Template Literals

یکی از مشکلاتی که از گذشته، برنامه‌نویسان جاوا اسکریپت با آن درگیر بوده‌اند، تعریف رشته‌های طولانی و چند خطی بوده است. به خصوص زمانی که نیاز به درج تعدادی متغیر در بخش‌های خاصی از این رشته‌ها باشد.

برای حل این مشکل، در ES6 روش جدیدی برای تعریف رشته‌ها به وجود آمده است. در این روش به جای استفاده از Single Quotes یا Double Quotes برای تعریف رشته‌ها از کاراکتر "`" (Backtick) استفاده می‌شود. (کلید مربوط به این کاراکتر، بالای کلید Tab قرار دارد.)

تفاوت‌های اصلی این روش با روش‌های قبلی به شرح زیر است : چند نمونه از استفاده از این روش را در قطعه کد زیر می‌توان مشاهده کرد.

let name = 'Hamid' , age = 20;
`My name is ${name}`;
← "My name is Hamid"

`Hello World!
My name is ${name} and It's my car
My profile folder is : c:\\Users\\${name}`;
← "Hello World!
My name is Hamid and It's my car
My profile folder is : c:\Users\Hamid"

`I'm ${age}, and my brother is two years older. So he is ${age + 2}`;
← "I'm 20, and my brother is two years older. So he is 22"

تعریف رشته‌ها با این روش را اصطلاحاً Template Literal می‌نامند. استفاده از این روش برای تعریف رشته‌های طولانی بسیار مفید بوده و کاربرد آن در بین برنامه‌نویسان جاوا اسکریپت روز به روز در حال افزایش است.