در جاوااسکریپت، دادهی متنی به عنوان رشته (string) ذخیره میشود. نوع جداگانهای برای یک کاراکتر مفرد وجود ندارد.
فرمت درونی برای رشتهها همیشه UTF-16 است، و به رمزگذاری صفحه بستگی ندارد.
کوتیشنها
بیایید انواع کوتیشنها را یادآوری کنیم.
رشتهها میتوانند در کوتیشنهای تکی، دوتایی یا backtickها محصور شوند:
let single = 'کوتیشن تکی';
let double = "کوتیشن دوتایی";
let backticks = `هاbacktick`;
کوتیشنهای تکی و دوتایی اساسا یکسان هستند. اگرچه، backtickها، با پیچیدن هر عبارتی در {...}$، به ما اجازه میدهند که آن عبارت را درون رشته قرار دهیم:
function sum(a, b) {
return a + b;
}
alert(`1 + 2 = ${sum(1, 2)}.`); // 1 + 2 = 3.
یکی دیگر از مزایای استفاده از backtickها این است که اجازه میدهند تا رشته را در چند خط بنویسیم:
let guestList = `مهمانها:
* John
* Pete
* Mary
`;
alert(guestList); // لیستی از مهمانها، در چند خط
طبیعی به نظر میرسد نه؟ اما کوتیشنهای تکی یا دوتایی این چنین کار نمیکنند.
اگر ما با استفاده از آنها تلاش کنیم در چند خط بنویسیم، یک ارور به وجود خواهد آمد:
let guestList = "Guests: // Error: Unexpected token ILLEGAL
* John";
کوتیشنهای تکی و دوتایی از زمان بسیار قدیم در زبان وجود داشتند زمانی که نیاز به رشتههای چند خطی خیلی به چشم نمیآمد. Backtickها بعدها به وجود آمدند و به این ترتیب چند کاره هستند.
Backtickها به ما اجازه میدهند که یک “تابع الگو” قبل از backtick اول مشخص کنیم. سینتکس اینگونه است: func`string`. تابع func به طور خودکار صدا زده میشود، رشته را دریافت میکند و عبارات را ایجاد میکند و میتواند با آنها فرایندی انجام دهد. به این “الگوهای برچسب گذاری شده” میگویند. این ویژگی پیادهسازی الگوهای سفارشی را آسانتر میکند، اما در عمل خیلی کم استفاده میشود. میتوانید درباره آن در کتاب راهنما بیشتر بخوانید.
کاراکترهای خاص
اینکه با کوتیشنهای تکی و دوتایی رشتههای چند خطی بسازیم، با استفاده از “کاراکتر خط جدید”، که به صورت \n نوشته میشود، امکان پذیر است که یک خط جدید را مشخص میکند:
let guestList = "مهمانها:\n * John\n * Pete\n * Mary";
alert(guestList); // لیستی چند خطی از مهمانها، درست مانند عبارت بالا
برای مثال، این دو خط برابر هستند، فقط به طور متفاوتی نوشته شدهاند:
let str1 = "Hello\nWorld"; // "ایجاد دو خط با استفاده از "نماد خط جدید
// هاbacktick ایجاد دو خط با استفاده از خط جدید و
let str2 = `Hello
World`;
alert(str1 == str2); // true
<<<<<<< HEAD کاراکترهای “خاص” دیگر و غیر متداول هم هستند:
There are other, less common special characters:
18b1314af4e0ead5a2b10bb4bacd24cecbb3f18e
| کاراکتر | توضیحات |
|---|---|
| <<<<<<< HEAD | |
\n |
خط جدید |
\r |
فایلهای متنی ویندوز از ترکیب دو کاراکتر \r\n برای نمایش یک خط جدید استفاده میکند، در حالی که برای سیستمهای غیر ویندوزی \n این کار را انجام میدهد. |
دلیل آن مربوط به گذشتهها است. بیشتر نرمافزارهای ویندوزی \n را هم میشناسند. |
|
\', \", \` |
کوتیشنها |
\\ |
Backslash |
\t |
Tab |
\b, \f, \v |
Backspace, Form Feed, Vertical Tab – برای کامل بودن مطالب گفته شدهاند، از قدیم وجود دارند، امروزه استفاده نمیشوند (شما میتوانید همین حالا آنها را فراموش کنید). |
تمام کاراکترهای خاص با یک کاراکتر backslash \ شروع میشوند. همچنین به آن “کاراکتر فرار (escape character)” هم میگویند.
چون این کاراکتر خاص است، اگر بخواهیم یک backslash \ واقعی درون رشته نشان دهیم، باید آن را دوبل کنیم:
alert( `The backslash: \\` ); // The backslash: \
کوتیشنهای «escaped» \'، \"، \` برای اضافه کردن یک کوتیشن به رشتهای که در همان نوع کوتیشن قرار گرفته است استفاده میشوند.
برای مثال:
alert( 'I\'m the Walrus!' ); // I'm the Walrus!
همانطور که میبینید، باید قبل از کوتیشن داخلی backslash \ بیاریم، وگرنه در غیر این صورت کوتیشن پایان رشته را نمایش میدهد.
قطعا فقط کوتیشنهایی که با کوتیشنهای پایانی یکسان هستند باید فراری شوند. پس، به عنوان یک راه حل زیباتر، به جای آن میتوانیم به کوتیشنهای دوتایی یا backtickها سوییچ کنیم:
alert( "I'm the Walrus!" ); // I'm the Walrus!
<<<<<<< HEAD
در کنار این کاراکترهای خاص، همچنین یک نشان خاص برای کدهای Unicode \u… وجود دارد که کمی بعدتر در این فصل آن را پوشش میدهیم.
Besides these special characters, there’s also a special notation for Unicode codes \u…, it’s rarely used and is covered in the optional chapter about Unicode.
18b1314af4e0ead5a2b10bb4bacd24cecbb3f18e
طول رشته
ویژگی length دارای طول رشته است:
alert( `My\n`.length ); // 3
در نظر داشته باشید که \n یک کاراکتر “خاص” مفرد است، پس طول در واقع 3 است.
length یک ویژگی استبعضی اوقات افرادی که زمینهای در بعضی زبانهای برنامه نویسی دیگر دارند اشتباها str.length() را به جای نوشتن str.length صدا میزنند. اینگونه کار نمیکند.
<<<<<<< HEAD
لطفا در نظر داشته باشید که str.length یک ویژگی عددی است نه یک تابع. نیازی به اضافه کردن پرانتر بعد از آن نیست.
Please note that str.length is a numeric property, not a function. There is no need to add parenthesis after it. Not .length(), but .length.
18b1314af4e0ead5a2b10bb4bacd24cecbb3f18e
دسترسی داشتن به کاراکترها
<<<<<<< HEAD
برای دریافت یک کاراکتر در موقعیت pos، از براکتها استفاده کنید یا متد str.charAt(pos) را صدا بزنید. اولین کاراکتر از موقعیت صفر شروع میشود:
To get a character at position pos, use square brackets [pos] or call the method str.at(pos). The first character starts from the zero position:
18b1314af4e0ead5a2b10bb4bacd24cecbb3f18e
let str = `Hello`;
// اولین کاراکتر
alert( str[0] ); // H
alert( str.at(0) ); // H
// آخرین کاراکتر
alert( str[str.length - 1] ); // o
alert( str.at(-1) );
<<<<<<< HEAD
براکتها روش مدرن دریافت کاراکتر هستند، در حالی که charAt بنا به دلایلی مربوط به تاریخچه زبان وجود دارد.
تنها تفاوت میان آنها این است که اگر کاراکتری پیدا نشود، [] مقدار undefined را برمیگرداند، و charAt یک رشته خالی را برمیگرداند:
As you can see, the .at(pos) method has a benefit of allowing negative position. If pos is negative, then it’s counted from the end of the string.
So .at(-1) means the last character, and .at(-2) is the one before it, etc.
The square brackets always return undefined for negative indexes, for instance:
18b1314af4e0ead5a2b10bb4bacd24cecbb3f18e
let str = `Hello`;
<<<<<<< HEAD
alert( str[1000] ); // undefined
alert( str.charAt(1000) ); // '' (یک رشته خالی)
=======
alert( str[-2] ); // undefined
alert( str.at(-2) ); // l
>>>>>>> 18b1314af4e0ead5a2b10bb4bacd24cecbb3f18e
همچنین ما میتوانیم با استفاده از for..of برای کاراکترها حلقه بزنیم:
for (let char of "Hello") {
alert(char); // H,e,l,l,o (و غیره "l" سپس ،"e" سپس ،"H" میشود char)
}
رشتهها تغییرناپذیر هستند
رشتهها در جاوااسکریپت نمیتوانند تغییر کنند. اینکه یک کاراکتر را تغییر دهیم غیر ممکن است.
بیایید برای نشان دادن اینکه این کار نخواهد کرد امتحانش کنیم:
let str = 'Hi';
str[0] = 'h'; // ارور میدهد
alert( str[0] ); // کار نمیکند
یک راه حل این است که رشتهای کاملا جدید بسازیم و str را به جای رشتهی قدیمی برابر با آن قرار دهیم.
برای مثال:
let str = 'Hi';
str = 'h' + str[1]; // رشته را جایگزین میکنیم
alert( str ); // hi
در بخشهای بعدی مثالهای بیشتری از این خواهیم دید.
تغییر بزرگی و کوچکی حروف
متدهای toLowerCase() و toUpperCase() بزرگی و کوچکی حروف را تغییر میدهند:
alert( 'Interface'.toUpperCase() ); // INTERFACE
alert( 'Interface'.toLowerCase() ); // interface
یا اگر بخواهیم یک کاراکتر را به حرف کوچک آن تبدیل کنیم اینگونه عمل میکنیم:
alert( 'Interface'[0].toLowerCase() ); // 'i'
جستجو برای یک زیر رشته
چند راه برای گشتن به دنبال یک زیر رشته در یک رشته وجود دارد.
متد str.indexOf
متد اول str.indexOf(substr, pos) است.
این متد به دنبال substr درون str میگردد، و از موقعیت pos داده شده شروع میکند، و موقعیتی که زیر رشته مورد نظر پیدا شد یا اگر چیزی پیدا نشد -1 را برمیگرداند.
برای مثال:
let str = 'Widget with id';
alert( str.indexOf('Widget') ); // 0 ،در شروع رشته پیدا شد 'Widget' چون
alert( str.indexOf('widget') ); // -1 ،چیزی پیدا نشد، جستجو به بزرگی یا کوچکی حروف حساس است
alert( str.indexOf("id") ); // 1 ،(است id دارای ..idget) در موقعیت 1 پیدا شد "id"
پارامتر اختیاری دوم به ما اجازه جستجو از موقعیت داده شده را میدهد.
برای مثال، اولین "id" که وجود دارد در موقعیت 1 است. برای پیدا کردن بعدی، بیایید جستجو را از موقعیت 2 شروع کنیم:
let str = 'Widget with id';
alert( str.indexOf('id', 2) ) // 12
اگر ما مشتاق این هستیم که تمام آنها را پیدا کنیم، میتوانیم indexOf را دورن یک حلقه اجرا کنیم. تمام صدازدنهای جدید با موقعیتی بعد از موقعیت زیر رشتهی پیدا شده قبلی انجام میشود:
let str = 'As sly as a fox, as strong as an ox';
let target = 'as'; // بیایید به دنبال آن بگردیم
let pos = 0;
while (true) {
let foundPos = str.indexOf(target, pos);
if (foundPos == -1) break;
alert( `Found at ${foundPos}` );
pos = foundPos + 1; // جستجو را از موقعیت بعدی ادامه بده
}
الگوریتم یکسان را میتوان کوتاهتر نوشت:
let str = "As sly as a fox, as strong as an ox";
let target = "as";
let pos = -1;
while ((pos = str.indexOf(target, pos + 1)) != -1) {
alert( pos );
}
متد str.lastIndexOf(substr, position)یک متد مشابه str.lastIndexOf(substr, position) هم وجود دارد که از انتهای رشته تا آغاز آن جستجو میکند.
این متد زیر رشتههای پیدا شده را با ترتیب برعکس لیست میکند.
یک چیز ناخوشایند در رابطه با indexOf در if وجود دارد. ما نمیتوانیم آن را اینگونه درون if بگذاریم:
let str = "Widget with id";
if (str.indexOf("Widget")) {
alert("We found it"); // !کار نمیکند
}
در مثال بالا alert نمایش نمیدهد زیرا str.indexOf("Widget") مقدار 0 را برمیکرداند (به این معنی که زیر رشته مورد نظر را در موقعیت آغازین پیدا کرد). درست است، اما if مقدار 0 را با false برابر فرض میکند.
بنابراین، ما باید در واقع -1 را بررسی کنیم، به این شکل:
let str = "Widget with id";
if (str.indexOf("Widget") != -1) {
alert("We found it"); // !حالا کار میکند
}
متدهای includes، startsWith، endsWith
متد مدرنتر str.includes(substr, pos) با وابستگی به اینکه رشته str درون خودش دارای زیر رشتهی substr است یا نه مقدار true/false را برمیگرداند.
اگر نیاز داشته باشیم که وجود یک زیر رشته را بررسی کنیم، اما به موقعیت آن نیازی نداریم این متد انتخاب مناسبی است:
alert( "Widget with id".includes("Widget") ); // true
alert( "Hello".includes("Bye") ); // false
آرگومان دوم و اختیاری str.includes موقعیتی است که جستجو از آن شروع میشود:
alert( "Widget".includes("id") ); // true
alert( "Widget".includes("id", 3) ); // false وجود ندارد پس "id" از موقعیت 3 هیج
متدهای str.startsWith(بررسی شروع شدن رشته با یک زیر رشته) و str.endsWith(بررسی پایان یافتن رشته با یک زیر رشته) دقیقا کاری را که میگویند انجام میدهند:
alert( "Widget".startsWith("Wid") ); // true شروع میشود پس "Wid" با "Widget"
alert( "Widget".endsWith("get") ); // true پایان مییابد پس "get" با "Widget"
گرفتن یک زیر رشته
در جاوااسکریپت 3 متد برای گرفتن یک زیر رشته وجود دارد: substring، substr و slice.
str.slice(start [, end])-
قسمتی از رشته را از موقعیت
startتاend(شاملendنمیشود) را برمیگرداند.برای مثال:
let str = "stringify"; alert( str.slice(0, 5) ); // 'strin' :زیر رشته از 0 تا 5 (شامل 5 نمیشود) alert( str.slice(0, 1) ); // 's' :از 0 تا 1، اما شامل 1 نمیشود، پس فقط کاراکتری که در 0 استاگر هیچ آرگومان دومی در کار نباشد، سپس
sliceتا آخر رشته میرود:let str = "stringify"; alert( str.slice(2) ); // 'ringify' :از موقعیت دوم تا آخرمقدارهای منفی برای
start/endهم ممکن هستند. آنها به این معنی هستند که موقعیت از آخر رشته شمارش میشود:let str = "stringify"; // از موقعیت 4 از سمت راست شروع میشود، در موقعیت 1 از سمت راست پایان مییابد alert( str.slice(-4, -1) ); // 'gif' str.substring(start [, end])-
قسمتی از رشته بین
startوendرا برمیگرداند (شاملendنمیشود).این متد تقریبا مشابه با
sliceاست، اما این اجازه را میدهد کهstartبیشتر ازendباشد (در این صورت مقدارهایstartوendرا جابجا میکند).برای مثال:
let str = "stringify"; // یکسان هستند substring این دو برای alert( str.substring(2, 6) ); // "ring" alert( str.substring(6, 2) ); // "ring" // ...اینطور نیست slice اما برای alert( str.slice(2, 6) ); // "ring" (یکسان است) alert( str.slice(6, 2) ); // "" (یک رشته خالی)آرگومانهای منفی (برخلاف slice) پشتیبانی نمیشوند، با آنها مانند
0رفتار میشود. str.substr(start [, length])-
قسمتی از رشته از
start، تاlength(طول) داده شده را برمیگرداند.در تضاد با متدهای قبلی، این متد به ما اجازه میدهد که به جای موقعیت پایانی
length(طول) را تعیین کنیم:let str = "stringify"; alert( str.substr(2, 4) ); // 'ring' :از موقعیت دوم 4 کاراکتر را بگیراولین آرگومان میتواند برای شمارش از آخر، منفی باشد:
let str = "stringify"; alert( str.substr(-4, 2) ); // 'gi' :از موقعیت چهارم 2 کاراکتر را بگیر
بیایید این متدها را برای جلوگیری از هر گمراهی خلاصه کنیم: