۸ دسامبر ۲۰۲۲

انواع داده

یک مقدار در جاوااسکریپت همیشه از یک نوع مشخص است. برای مثال، رشته (string) یا عدد (number).

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

ما می‌توانیم هر نوعی را داخل متغیر قرار دهیم. برای مثال، یک متغیر می‌تواند یک بار رشته باشد و سپس یک عدد را ذخیره کند:

// اروری وجود نخواهد داشت
let message = "سلام";
message = 123456;

زبان‌های برنامه‌نویسی‌ای، مثل جاوااسکریپت، که چنین امکانی به شما می‌دهند “Dynamically Typed” نامیده می‌شوند. به این معنی که انواعی از داده وجود دارد اما متغیرها محدود به آنها نیستند.

Number

let n = 123;
n = 12.345;

نوع number (عدد) اعداد صحیح و اعداد اعشاری را شامل می‌شود.

عملیات مختلفی در مورد اعداد وجود دارد مانند ضرب * ، تقسیم / ، جمع + ، تفریق - و غیره.

همینطور بجز اعداد معمولی، اعداد خاصی نیز وجود دارند که به همین نوع از متغیرها مربوط می‌شوند. یعنی: Infinity (بی‌نهایت)، Infinity- (منفی بی‌نهایت) و NaN.

  • Infinity بیانگر علامت ریاضیاتیِ بی‌نهایت ∞ است. این مقدار خاص بوده که از هر عدد دیگری بزرگتر است.

    از تقسیم هر عددی با صفر به این مقدار می‌رسیم:

    alert( 1 / 0 ); // Infinity

    یا به طور مستقیم نیز به آن دسترسی داریم:

    alert( Infinity ); // Infinity
  • NaN بیانگر یک اشکال محاسباتی است. این مقدار نتیجه یک عملیات ریاضیاتی غلط یا تعریف‌نشده است. برای نمونه:

    alert( "not a number (چیزی غیر از عدد)" / 2 ); // NaN ،چنین تقسیمی اشتباه است

    NaN جسبنده است. هر عمل ریاضیاتی روی NaN مقدار NaN را برمی‌گرداند:

    alert( NaN + 1 ); // NaN
    alert( 3 * NaN ); // NaN
    alert( "not a number (چیزی غیر از عدد)" / 2 - 1 ); // NaN

    در نتیجه اگر جایی در عبارت ریاضیاتی NaNوجود داشته باشد، بر روی تمام معادله تاثیر می‌گذارد (فقط یک استثنا برای آن وجود دارد: NaN ** 0 برابر با 1 است).

عملیات ریاضیاتی امن هستند

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

اسکریپت ما هیچگاه با خطای مرگباری (fatal error) مواجه نخواهد شد. در بدترین حالت NaN را به عنوان نتیجه خواهیم گرفت.

مقدارهای عددی خاص به طور رسمی به نوع “number” تعلق دارند. البته آنها به معنای واقعی این کلمه، عدد نیستند.

ما در فصل اعداد بیشتر درباره کار کردن با اعداد خواهیم دید.

BigInt

در جاوااسکریپت، نوع “number” نمی‌تواند مقدارهای صحیح بیشتر از (253-1) (برابر با 9007199254740991) یا اعداد منفی کمتر از -(253-1) برای اعداد منفی را نشان دهد.

اگر بخواهیم خیلی دقیق باشیم، نوع “number” می‌تواند اعداد صحیح بزرگ‌تر را ذخیره کند (اعدادی تا 1.7976931348623157 * 10308) اما بیرون از محدوده امن عدد صحیح (253-1)±، خطای دقت به وجود می‌آید چون تمام رقم‌ها درون حافظه 64 بیتی جای نمی‌گیرند. بنابراین یک مقدار تقریبی ممکن است ذخیره شود.

برای مثال، این دو عدد (کمی بیشتر از محدوده امن) یکسان هستند:

console.log(9007199254740991 + 1); // 9007199254740992
console.log(9007199254740991 + 2); // 9007199254740992

بنابراین، تمام اعداد صحیح فرد که از (253-1) بیشتر هستند نمی‌توانند در نوع “number” ذخیره شوند.

محدوده (253-1)± برای بیشتر کارها کافی است، اما گاهی به اعداد بسیار بزرگ نیاز داریم، برای مثال در کریپتوگرافی یا timestamps با دقت میکرو ثانیه.

نوع BigInt برای نمایش دادن اعداد صحیح که طول دلخواهی دارند به تازگی به زبان اضافه شده است.

یک مقدار BigInt با اضافه کردن n به آخر یک عدد صحیح ایجاد می‌شود:

// بودن آن است BigInt در آخر به معنای "n" حرف
const bigInt = 1234567890123456789012345678901234567890n;

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

مشکلات سازگاری

در حال حاضر، BigInt در Firefox/Chrome/Edge/Safari پشتیبانی می‌شوند، اما در IE خیر.

شما می‌توانید جدول سازگاری BigInt در MDN را برای اینکه بدانید کدام نسخه از مرورگرها پشتیبانی می‌شوند، بررسی کنید.

String

در جاوااسکریپت یک رشته (string) باید توسط کوتِیشِن‌ها احاطه شود.

let str = "سلام";
let str2 = 'کوتیشن‌های تکی نیز مورد قبول هستند';
let phrase = `دیگر را جای داد ${str} می‌توان یک`;

در جاوااسکریپت سه نوع کوتِیشِن داریم:

  1. Double qoutes (کوتیشن دوتایی) مانند "Hello".
  2. Single qoutes (کوتیشن تکی) مانند 'Hello'.
  3. Backticks مانند `Hello`.

Double quotes و Single quotes همان کوتِیشِن‌های عادی هستند و در جاوااسکریپت تفاوتی بین آنها وجود ندارد.

Backticks کوتیشن‌هایی با “قابلیت‌های گسترده” هستند. به وسیله‌ی آنها می‌توانیم داخل یک رشته، با قرار دادن عبارات و دستورات جاوااسکریپت در {...}$ آنها را بنویسیم.

let name = "John";

// تعبیه کردن یک متغیر
alert( `Hello, ${name}!` ); // Hello, John!

// تعبیه کردن یک عبارت
alert( `the result is ${1 + 2}` ); // the result is 3 (ترجمه: نتیجه 3 است)

عبارتی که در {…}$ قرار می‌گیرد اجرا شده و نتیجه آن در رشته مورد نظر قرار می‌گیرد. ما می‌توانیم هر چیزی را درون آن قرار دهیم: یک متغیر مثل name یا یک عبارت محاسباتی مثل 1 + 2 یا حتی چیزی پیچیده‌تر.

توجه داشته باشید که این فقط می‌تواند در Backticks انجام شود. کوتیشن‌های دیگر قابلیت تعبیه کردن را ندارند:

alert( "the result is ${1 + 2}" ); // the result is ${1 + 2} (کاری نمی‌کنند double quotes)

در مورد رشته‌ها در فصل رشته‌ها بیشتر صحبت خواهیم کرد.

نوع داده‌ای برای کاراکترها وجود ندارد

در بعضی از زبان‌ها، یک نوع خاص “کاراکتر” برای کاراکتر تکی وجود دارد. برای مثال، در زبان C و Java به آن “char” می‌گویند.

در جاوااسکریپت، چنین نوعی وجود ندارد. تنها یک نوع وجود دارد: string. یک رشته شاید شامل صفر کاراکتر (خالی)، یک کاراکتر یا تعداد زیادی کاراکتر باشد.

Boolean (نوع منطقی)

نوع Boolean فقط یکی از دو مقدار true و false را شامل می‌شود.

این نوع معمولا برای ذخیره مقدار بله یا خیر استفاده می‌شود. true به معنی “بله، درست” و false به معنی “خیر، نادرست” می‌باشد.

برای نمونه:

let nameFieldChecked = true; // بله، قسمت نام تیک خورده است
let ageFieldChecked = false; // خیر، قسمت سن تیک نخورده است

مقدارهای Boolean به عنوان یک نتیجه‌ی مقایسه هم بدست می‌آیند:

let isGreater = 4 > 1;

alert( isGreater ); // true (نتیجه مقایسه "بله" است)

ما booleanها را با جزییات بیشتر در فصل عملگر های منطقی بررسی می‌کنیم.

مقدار “null”

مقدار خاص null به هیچ کدام از نوع‌هایی که بالا توضیح داده شد تعلق ندارد.

Null از خودش یک نوع داده جداگانه را تشکیل می‌دهد که فقط حاوی مقدار null است:

let age = null;

در جاوااسکریپت null مانند بعضی از زبان‌های برنامه‌نویسی به معنی وجود نداشتن یک شیء یا به معنی null pointer نیست.

Null صرفا یک مقدار خاص است که نمایانگر “خالی بودن”، “هیچ بودن” و “مشخص نبودن مقدار” می‌باشد.

کد بالا بیان می‌کند که age مشخص نیست.

مقدار “undefined”

مقدار خاص undefined هم جداست. این مقدار درست مثل null، از خودش یک نوع می‌سازد.

undefined بدین معنی‌ است که “مقداری اختصاص نیافته است”.

اگر متغیری تعریف کنیم و مقداری به آن اختصاص ندهیم، مقدار آن undefined خواهد بود:

let x;

alert(x); // داده می‌شود "undefined" مقدار

از لحاظ فنی، امکان تخصیص دادن undefined به هر متغیری وجود دارد :

let x = 123;

// undefined تغییر مقدار به
x = undefined;

alert(x); // "undefined"

…اما ما این کار را پیشنهاد نمی‌کنیم. معمولا، برای اختصاص دادن مقدار “نامشخص” یا “خالی” به یک متغیر از null استفاده می‌شود، در حالی که undefined به عنوان یک مقدار اولیه برای چیزهای تخصیص داده نشده رزرو شده است.

شیءها و Symbolها

نوع object (شیء) از انواع خاص است.

انواع مختلف داده که تا اینجا مطالعه کردیم از انواع «primitive» (اولیه) بودند چرا که مقدار آنها فقط شامل یک چیز می‌شد (رشته یا عدد یا هر چیز دیگری). در مقابل، شیءها برای ذخیره مجموعه‌ای از داده‌ها به شکلی پیچیده‌تر استفاده می‌شوند.

شیءها به حدی مهم هستند که لایق طرز برخورد ویژه‌ای هستند. ما بعدا در فصل شیءها به سراغ آنها خواهیم رفت، بعد از اینکه درباره انواع primitive بیشتر یاد گرفتیم.

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

عملگر typeof

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

این عملگر به دو شکل قابل استفاده است:

  1. به عنوان عملگر : typeof x.
  2. به عنوان تابع : typeof (x).

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

با صدا زدن typeof x رشته کاراکتری حاوی نوع آن مقدار نمایش داد می‌شود:

typeof undefined // "undefined"

typeof 0 // "number"

typeof 10n // "bigint"

typeof true // "boolean"

typeof "foo" // "string"

typeof Symbol("id") // "symbol"

typeof Math // "object"  (1)

typeof null // "object"  (2)

typeof alert // "function"  (3)

سه خط آخر احتمالا نیاز به توضیحات بیشتری دارد:

  1. Math یک شیء built-in (از پیش نوشته شده در هسته زبان) است که عملیات متنوع ریاضیاتی را در اختیار ما قرار می‌دهد. ما آن را در فصل اعداد یاد می‌گیریم. در اینجا صرفا یک مثال از آن را نمایش دادیم.
  2. خروجی typeof null برابر با "object" است. این یک خطا در طرز کار typeof می‌باشد که از روزهای اول در جاوااسکریپت وجود داشته و به منظور سازگاری باقی مانده است. مطمئنا null یک object نیست. خودِ null یکی از انواع داده در جاوااسکریپت است.
  3. خروجی typeof alert برابر با "function" است چرا که alert خودش هم یک تابع است. ما در بخش‌های بعدی با تابع‌ها بیشتر آشنا خواهیم شد و خواهیم آموخت که نوعی تحت عنوان function در جاوااسکریپت نداریم. تابع‌ها در اصل از نوعِ object هستند. اما عملگر typeof با آنها به طرز دیگری برخورد می‌کند و function را برمی‌گرداند. این هم از روزهای اول جاوااسکریپت وجود داشته است. به طور فنی، این رفتار درست نیست، اما در عمل می‌تواند مفید باشد.
سینتکس typeof(x)

شاید سینتکس دیگری را دیده باشید: typeof(x). این با typeof x یکسان است.

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

معمولا چنین پرانتزهایی یک عبارت ریاضیاتی، مانند (2 + 2)، را شامل می‌شوند اما اینجا آن‌ها فقط آرگومان (x) را دارند. از لحاظ سینتکس، آن‌ها به ما این امکان را می‌دهند که از وجود فاصله بین عملگر typeof و آرگومانش جلوگیری کنیم و بعضی از اشخاص آن را دوست دارند.

بعضی از اشخاص typeof(x) را ترجیح می‌دهند اگرچه سینتکس typeof x رایج‌تر است.

خلاصه

در جاوااسکریپت 8 نوع داده پایه‌ای وجود دارد.

  • هفت نوع داده اولیه:
    • number برای اعداد از هر دسته‌ای: عدد صحیح یا اعشاری، اعداد صحیح به (253-1)± محدود می‌شوند.
    • bigint برای اعداد صحیح با طول دلخواه است.
    • string برای رشته‌ها. یک رشته ممکن است صفر کاراکتر یا بیشتر داشته باشد، هیج نوع جداگانه‌ی تک کاراکتری وجود ندارد.
    • boolean برای true/false.
    • null برای مقدارهای نامشخص – یک نوع مستقل که فقط یک مقدار null دارد.
    • undefined برای مقدارهای تخصیص نیافته – یک نوع مستقل که فقط یک مقدار undefined دارد.
    • symbol برای شناسه‌های یکتا.
  • و یک نوع داده non-primitive :
    • object برای ساختارهای پیچیده‌تر داده.

عملگر typeof به شما اجازه می‌دهد نوع مقدار ذخیره شده در یک متغیر را تشخصی دهید.

  • معمولا به صورت typeof x استفاده می‌شود، اما typeof(x) هم قابل قبول است.
  • یک رشته شامل اسم نوع را برمی‌گرداند، مثل "string".
  • برای null مقدار "object" را نمایش می‌دهد – این یک خطا در خودِ زبان است، در واقع null یک object نیست.

در فصل‌های بعدی، ما روی نوع‌های “primitive” تمرکز می‌کنیم و هنگامی که با آنها بیشتر آشنا شدیم، به سراغ شیءها می‌رویم.

تمارین

اهمیت: 5

خروجی این اسکریپت چه خواهد بود :

let name = "Ilya";

alert( `hello ${1}` ); // ?

alert( `hello ${"name"}` ); // ?

alert( `hello ${name}` ); // ?

Backticks عبارت داخل {...}$ را در رشته قرار می‌دهد.

let name = "Ilya";

// عبارت، عدد 1 است
alert( `hello ${1}` ); // hello 1

// است "name" عبارت، رشته
alert( `hello ${"name"}` ); // hello name

// عبارت، یک متغیر است، مقدار آن را داخل رشته قرار می‌دهد
alert( `hello ${name}` ); // hello Ilya
نقشه آموزش