بررسی رشته در جاوا اسکریپت — از صفر تا صد

۶۷ بازدید
آخرین به‌روزرسانی: ۰۷ شهریور ۱۴۰۲
زمان مطالعه: ۳ دقیقه
بررسی رشته در جاوا اسکریپت — از صفر تا صد

زمانی که می‌خواهیم به بررسی رشته در جاوا اسکریپت بپردازیم، typeof به خوبی عمل می‌کند، مگر این که از یک «پوشش شیء ابتدایی» استفاده شده باشد که رویه نامطلوبی محسوب می‌شود. بررسی این رشته‌ها در جاوا اسکریپت کمی دشوار است. این وضعیت مشابه بررسی NaN در جاوا اسکریپت است، اما خوشبختانه کار با رشته‌ها به مقدار زیادی آسان است. زمانی که این بررسی را انجام می‌دهیم، اگر یک مقدار از نوع رشته در جاوا اسکریپت باشد، typeof عملکرد خوبی دارد:

1const aBoolean = true
2const aNumber = 37
3const aString = "A String"
4const wrappedString = new String( "An 'Object-Wrapped' String" )
5
6console.log(typeof aBoolean) // "boolean"
7console.log(typeof aNumber) // "number"
8console.log(typeof aString) // "string"
9console.log(typeof wrappedString) // "object"

اما typeof در مورد رشته‌هایی که با new String()‎ ساخته شده‌اند عملکرد درستی ندارد. این نوع رشته‌ها به نام «پوشش شیء ابتدایی» (Primitive Object Wrapper) نامیده می‌شوند. ایجاد رشته‌های پوشش شیء بسیار نادر است و چنان که در بخش بعدی توضیح خواهیم داد، عموماً توصیه نمی‌شود.

چرا پوشش شیئ ابتدایی بد است؟

اگر به راهنماهای مختلف توجه کنید می‌بینید که اغلب اعلام می‌کنند استفاده از پوشش شیء ابتدایی کار خوبی نیست. برای نمونه:

  • راهنمای استایل گوگل برای جاوا اسکریپت می‌گوید هرگز از پوشش‌های شیء ابتدایی استفاده نکنید (+).
  • داگلاس کراکفورد عموماً توصیه می‌کند که پوشش‌های شیء ابتدایی باید منسوخ شوند (+).

در واقع هیچ کسی وجود ندارد که توصیه به استفاده از آن‌ها کرده باشد و پوشش‌های شیء ابتدایی مورد تنفر عمومی هستند.

چگونه از استفاده از پوشش شیئ اجتناب کنیم؟

شاید تنها جایی که بحث پوشش‌های شیء ابتدایی به کار می‌آید، در سؤالات مصاحبه‌های استخدامی باشد که عموماً به روش‌های استفاده از typeof برای بررسی نوع مربوط هستند. در واقع، در ادامه سه روش برای فراخوانی یک رشته می‌بینید که تقریباً همه برنامه‌نویسان جاوا اسکریپت صرفاً از روش اول اطلاع دارند:

1const someString = "37" // "37" is a string literal
2const alsoSomeString = String(37) // Coerce the value of 37 to a string
3const someBadBadString = new String(37) // Wrap the string in an object

پوشش‌های شیئ سردرگم‌کننده هستند

ایجاد صریح پوشش با استفاده از عملکرد new یک رویه بد محسوب می‌شود. از سوی دیگر فراخوانی تابع بدون عملگر new کاملاً معتبر است، چون تلاش می‌کنیم تا ورودی را به نوع ابتدایی متناظر تبدیل کرده و یک مقدار از نوع ابتدایی بازگشت دهیم.

علاوه بر تلاش برای تغییر دادن مقدار بازگشتی typeof یک کاربرد دیگر نیز در مورد پوشش‌های شیء وجود دارد که موجب سردرگمی می‌شود و آن type coercion است. یک تابع می‌تواند بدون کلیدواژه new استفاده شود تا یک مقدار به نوع ابتدایی کاهش یابد. به کد زیر توجه کنید:

1// Not recommended (primitive object wrapper):
2typeof new String(37) // object
3
4// Safe (type coercion with wrapper function):
5typeof String(37) // string
6
7// Primitive strings:
8"37" === "37" // true
9
10// Object-wrapped string:
11"37" === new String(37) // false
12
13// Type-coerced string:
14"37" === String(37) // true

بنابراین استفاده از تابع پوشششی بدون کلیدواژه new یک روش مفید برای کاهش یک مقدار به یک نوع ابتدایی است. از سوی دیگر، استفاده از کلیدواژه new یک پوشش شیء ابتدایی ایجاد می‌کند که رویه بدی محسوب می‌شود.

اگر پوشش‌های شیئ بد هستند، چرا وجود دارند؟

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

برای نمونه این حالت در زمان بررسی طول یک رشته با استفاده از مشخصه String.prototype.length یا جایگزینی همه رشته‌های فرعی درون یک رشته با استفاده از تابع ()String.prototype.replace به کار می‌آید:

1const greetings = "Hello world!"
2greetings.length // 12
3greetings.replace("e","a") // "Hallo world!"

در هر دوی این موارد، جاوا اسکریپت پوشش شیء را در پس‌زمینه برای ایجاد امکان ارجاع به مشخصه و متدهای شیء فراخوانی می‌کند.

تطبیق با یک پوشش شیئ

شاید از خود بپرسید در صورتی که پوشش‌های شیء مختلفی در کد وجود داشته باشند و بخواهید یک رشته را بررسی کنید، باید چه کار بکنید؟ در این صورت باید با دو قابلیت دیگر جاوا اسکریپت به نام کلیدواژه instanceof و تابع ()Object.prototype.toString.call آشنا باشید. در کد زیر با شیوه استفاده از تابع ()isString بهبودیافته آشنا خواهید شد:

1const goodString = "I've been a good string"
2console.log(typeof goodString) // string
3console.log(goodString instanceof String) // false
4console.log(Object.prototype.toString.call(goodString)) // [object String]
5
6const badString = new String("I've been a naughty string")
7console.log(typeof badString) // object
8console.log(badString instanceof String) // true
9console.log(Object.prototype.toString.call(badString)) // [object String]
10
11const isPrimitiveString = value => typeof value === "string"
12console.log(isPrimitiveString(goodString)) // true
13console.log(isPrimitiveString(badString)) // false
14
15const isObjectWrappedString = value => value instanceof String
16console.log(isObjectWrappedString(goodString)) // false
17console.log(isObjectWrappedString(badString)) // true
18
19const isString = value => typeof value === "string" || value instanceof String
20console.log(isString(goodString)) // true
21console.log(isString(badString)) // true
22
23const isStringAlternative = value => Object.prototype.toString.call(badString)==="[object String]"
24console.log(isStringAlternative(goodString)) // true
25console.log(isStringAlternative(badString)) // true

سخن پایانی

به طور کلی typeof در کاربردهای روزمره برای بررسی رشته بسیار کارآمد است. اما رشته‌های با پوشش شیء نیز در جاوا اسکریپت وجود دارند که در صورت نیاز مدیریت آن‌ها نیز چندان دشوار نخواهد بود. در مورد انواع ابتدایی که درون شیء پوشش یافته‌اند، کلیدواژه nstanceof و تابع instanceof keyword and the نوع مقدار را مشخص می‌سازند.

اگر این مطلب برای شما مفید بوده است، آموزش‌های زیر نیز به شما پیشنهاد می‌شوند:

==

بر اساس رای ۰ نفر
آیا این مطلب برای شما مفید بود؟
اگر بازخوردی درباره این مطلب دارید یا پرسشی دارید که بدون پاسخ مانده است، آن را از طریق بخش نظرات مطرح کنید.
منابع:
javascript-in-plain-english
نظر شما چیست؟

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *