متغیرها

متغیرها یک ساختار داده ای هستند که یک نام نماینده را به یک مقدار اختصاص می دهند. آنها می توانند حاوی داده هایی از هر نوع باشند.

نام متغیر را شناسه می نامند. یک شناسه معتبر باید از این قوانین پیروی کند:

  • شناسه ها می توانند شامل حروف یونیکد، علائم دلار ($)، نویسه های زیرخط (_)، ارقام (0-9)، و حتی برخی از کاراکترهای یونیکد باشند.
  • شناسه ها نمی توانند حاوی فضای خالی باشند، زیرا تجزیه کننده از فضای خالی برای جداسازی عناصر ورودی استفاده می کند. به عنوان مثال، اگر بخواهید به جای myVariable یک متغیر my Variable را صدا بزنید، تجزیه کننده دو شناسه my و Variable را می بیند و یک خطای نحوی ("token unnexpected: identifier") ایجاد می کند.
  • شناسه ها باید با یک حرف، زیرخط ( _ ) یا علامت دلار ( $ ) شروع شوند. برای جلوگیری از سردرگمی بین اعداد و شناسه‌ها، نمی‌توانند با اعداد شروع شوند:

    let 1a = true;
    
    > Uncaught SyntaxError: Invalid or unexpected token
    

    اگر جاوا اسکریپت اعداد را در ابتدای یک شناسه مجاز می‌کرد، به شناسه‌هایی که فقط از اعداد تشکیل شده‌اند اجازه می‌دادند و باعث تضاد بین اعداد استفاده‌شده به‌عنوان اعداد و اعداد استفاده‌شده به‌عنوان شناسه می‌شد:

    let 10 = 20
    
    10 + 5
    > ?
    
  • " کلمات رزرو شده " که قبلاً از نظر نحوی معنی دارند نمی توانند به عنوان شناسه استفاده شوند.

  • شناسه ها نمی توانند شامل کاراکترهای خاص باشند ( ! . , / \ + - * = ).

موارد زیر قوانین سختگیرانه ای برای ایجاد شناسه ها نیستند، اما بهترین روش های صنعت هستند که حفظ کد شما را آسان تر می کنند. اگر پروژه خاص شما دارای استانداردهای متفاوتی است، به جای آن از استانداردها پیروی کنید.

با پیروی از مثالی که توسط روش‌ها و ویژگی‌های داخلی جاوا اسکریپت تنظیم شده است، casel case (همچنین به عنوان "camelCase" تلطیف شده است) یک قرارداد بسیار رایج برای شناسه‌هایی است که از چندین کلمه تشکیل شده است. حالت شتر عمل بزرگ کردن حرف اول هر کلمه به جز حرف اول برای بهبود خوانایی بدون فاصله است.

let camelCasedIdentifier = true;

برخی از پروژه ها بسته به زمینه و ماهیت داده ها از قراردادهای نامگذاری دیگری استفاده می کنند. برای مثال، حرف اول یک کلاس معمولاً با حروف بزرگ نوشته می‌شود، بنابراین در نام‌های کلاس‌های چند کلمه‌ای معمولاً از یک نوع شتر استفاده می‌شود که معمولاً «جعبه شتر بالایی» یا پاسکال نامیده می‌شود.

class MyClass {

}

شناسه‌ها باید ماهیت داده‌هایی را که دارند به‌طور مختصر توصیف کنند (به عنوان مثال، currentMonthDays نام بهتری از theNumberOfDaysInTheCurrentMonth است) و در یک نگاه به وضوح خوانده شود ( originalValue بهتر از val است). شناسه‌های myVariable که در سراسر این ماژول استفاده می‌شوند، در زمینه نمونه‌های مجزا کار می‌کنند، اما در کد تولید بسیار مفید نیستند، زیرا هیچ اطلاعاتی در مورد داده‌هایی که دارند ارائه نمی‌دهند.

شناسه‌ها نباید در مورد داده‌هایی که دارند خیلی مشخص باشند، زیرا مقادیر آنها بسته به نحوه عملکرد اسکریپت‌ها روی آن داده‌ها یا تصمیم‌هایی که نگهدارنده‌های آینده می‌گیرند می‌تواند تغییر کند. برای مثال، متغیری که در ابتدا به miles شناسه داده می‌شد، ممکن است نیاز به تغییر به مقداری بر حسب کیلومتر در پروژه داشته باشد، و از نگهدارنده‌ها می‌خواهد که هر مرجعی را به آن متغیر تغییر دهند تا از سردرگمی آینده جلوگیری شود. برای جلوگیری از این امر، به جای آن distance به عنوان شناسه خود استفاده کنید.

جاوا اسکریپت هیچ امتیاز یا معنای خاصی به شناسه هایی که با کاراکترهای زیرخط ( _ ) شروع می شوند، نمی دهد، اما معمولاً برای نشان دادن اینکه یک متغیر، متد یا ویژگی "خصوصی" است، استفاده می شود، به این معنی که فقط برای استفاده در داخل در نظر گرفته شده است. زمینه شی که حاوی آن است، و نباید خارج از آن زمینه به آن دسترسی پیدا کرد یا تغییر داد. این قراردادی است که از زبان های برنامه نویسی دیگر منتقل شده است و قبل از اضافه شدن ویژگی های خصوصی جاوا اسکریپت است.

اعلام متغیر

راه های متعددی برای آگاه کردن جاوا اسکریپت از یک شناسه وجود دارد، فرآیندی به نام «اعلان» یک متغیر. یک متغیر با استفاده از کلمات کلیدی let ، const یا var اعلام می شود.

let myVariable;

let یا var برای اعلام متغیری که در هر زمان می توان آن را تغییر داد، استفاده کنید. این کلمات کلیدی به مفسر جاوا اسکریپت می گویند که رشته ای از کاراکترها یک شناسه است که ممکن است حاوی مقدار باشد.

هنگام کار در یک پایگاه کد مدرن، به جای var از let استفاده کنید. var هنوز در مرورگرهای مدرن کار می کند، اما برخی از رفتارهای غیر شهودی دارد که در نسخه های اولیه جاوا اسکریپت تعریف شده بودند، و بعداً برای حفظ سازگاری با عقب نمی توان آن را تغییر داد. let در ES6 اضافه شد تا برخی از مشکلات مربوط به طراحی var را برطرف کند.

یک متغیر اعلام شده با اختصاص مقداری به متغیر مقداردهی اولیه می شود. از یک علامت تساوی ( = ) برای تخصیص یا تخصیص مجدد یک مقدار به یک متغیر استفاده کنید. می توانید این کار را به عنوان بخشی از همان عبارتی که آن را اعلام می کند انجام دهید:

let myVariable = 5;

myVariable + myVariable
> 10

همچنین می توانید یک متغیر را با let (یا var ) بدون مقداردهی اولیه آن اعلام کنید. اگر این کار را انجام دهید، مقدار اولیه متغیر undefined است تا زمانی که کد شما به آن مقداری اختصاص دهد.

let myVariable;

myVariable;
> undefined

myVariable = 5;

myVariable + myVariable
> 10

متغیر با مقدار undefined با متغیر تعریف نشده ای که شناسه آن هنوز اعلام نشده است متفاوت است. ارجاع به متغیری که اعلان نکرده اید باعث خطا می شود.

myVariable
> Uncaught ReferenceError: myVariable is not defined

let myVariable;

myVariable
> undefined

ارتباط یک شناسه با یک مقدار به طور کلی "باید" نامیده می شود. نحوی که از کلیدواژه‌های let ، var یا const پیروی می‌کند، "لیست الزام آور" نامیده می‌شود و امکان چندین اعلان متغیر جدا شده با کاما را می‌دهد (که با نقطه ویرگول مورد انتظار ختم می‌شوند). این باعث می شود قطعه کد زیر از نظر عملکردی یکسان باشد:

let firstVariable,
     secondVariable,
     thirdVariable;
let firstVariable;
let secondVariable;
let thirdVariable;

تخصیص مجدد مقدار متغیر از let (یا var ) استفاده نمی کند، زیرا جاوا اسکریپت از قبل می داند که متغیر وجود دارد:

let myVariable = true;

myVariable
> true

myVariable = false;

myVariable
> false

می‌توانید متغیرها را بر اساس مقادیر موجود، مقادیر جدیدی تخصیص دهید:

let myVariable = 10;

myVariable
> 10

myVariable = myVariable * myVariable;

myVariable
> 100

اگر سعی کنید یک متغیر را با استفاده از let in یک محیط تولید مجدداً اعلام کنید، یک خطای نحوی دریافت خواهید کرد:

let myVariable = true;
let myVariable = false;
> Uncaught SyntaxError: redeclaration of let myVariable

ابزارهای توسعه دهنده مرورگرها در مورد اعلام مجدد letclass ) سهل گیرتر هستند، بنابراین ممکن است همان خطا را در کنسول توسعه دهنده خود مشاهده نکنید.

برای حفظ سازگاری مرورگر قدیمی، var امکان اعلام مجدد غیرضروری بدون خطا در هر زمینه را می‌دهد:

var myVariable = true;
var myVariable = false;

myVariable\
> false

const

از کلمه کلیدی const برای اعلام یک ثابت استفاده کنید، یک نوع متغیر که باید فورا مقداردهی اولیه شود و سپس قابل تغییر نیست. شناسه‌های ثابت‌ها از همه قوانین مشابه متغیرهای اعلام شده با استفاده از letvar ) پیروی می‌کنند:

const myConstant = true;

myConstant
> true

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

const myConstant;
Uncaught SyntaxError: missing = in const declaration

تلاش برای تغییر مقدار یک متغیر اعلام شده با const به روشی که ممکن است مقدار متغیر wit را با let (یا var ) تغییر دهید، یک خطای نوع ایجاد می کند:

const myConstant = true;

myConstant = false;
> Uncaught TypeError: invalid assignment to const 'myConstant'

با این حال، هنگامی که یک ثابت با یک شی مرتبط است، ویژگی های آن شی را می توان تغییر داد.

const constantObject = { "firstvalue" : true };

constantObject
> Object { firstvalue: true }

constantObject.secondvalue = false;

constantObject
> Object { firstvalue: true, secondvalue: false }

ثابتی که حاوی یک شی است یک مرجع تغییرناپذیر به یک مقدار داده قابل تغییر است. در حالی که خود ثابت را نمی توان تغییر داد، ویژگی های شی ارجاع شده را می توان تغییر داد، به آن اضافه کرد یا حذف کرد:

const constantObject = { "firstvalue" : true };

constantObject = false
> Uncaught TypeError: invalid assignment to const 'constantObject'

زمانی که انتظار ندارید متغیری دوباره تخصیص داده شود، بهترین کار این است که آن را ثابت کنید. استفاده از const به تیم توسعه شما یا نگهبانان آینده پروژه می‌گوید که آن مقدار را تغییر ندهند، تا از زیر پا گذاشتن مفروضاتی که کد شما در مورد نحوه استفاده از آن می‌سازد اجتناب کنند - به عنوان مثال، اینکه یک متغیر در نهایت با یک نوع داده مورد انتظار ارزیابی می‌شود.

دامنه متغیر

محدوده یک متغیر بخشی از یک اسکریپت است که در آن متغیر در دسترس است. خارج از محدوده متغیر، تعریف نمی شود – نه به عنوان یک شناسه حاوی مقدار undefined ، بلکه به گونه ای که گویی اعلام نشده است.

بسته به کلمه کلیدی که برای تعریف یک متغیر استفاده می‌کنید و زمینه‌ای که در آن آن را تعریف می‌کنید، می‌توانید متغیرها را برای بلوک عبارات ( محدوده بلوک )، توابع جداگانه ( حوزه تابع )، یا کل برنامه جاوا اسکریپت ( گستره جهانی ) قرار دهید.

محدوده را مسدود کنید

هر متغیری که با استفاده از let یا const اعلام می‌کنید به نزدیک‌ترین دستور بلوک حاوی آن اختصاص داده می‌شود، به این معنی که متغیر فقط در آن بلوک قابل دسترسی است. تلاش برای دسترسی به یک متغیر با محدوده بلوک خارج از بلوک حاوی آن، همان خطای تلاش برای دسترسی به متغیری را ایجاد می کند که وجود ندارد:

{
    let scopedVariable = true;
    console.log( scopedVariable );
}
> true

scopedVariable
> ReferenceError: scopedVariable is not defined

تا جایی که به جاوا اسکریپت مربوط می شود، یک متغیر با محدوده بلوکی خارج از بلوکی که آن را در بر می گیرد وجود ندارد . به عنوان مثال، می توانید یک ثابت را در داخل یک بلوک اعلام کنید، و سپس ثابت دیگری را در خارج از آن بلوک که از همان شناسه استفاده می کند، اعلام کنید:

{
  const myConstant = false;
}
const myConstant = true;

scopedConstant;
> true

اگرچه یک متغیر اعلام شده نمی تواند به بلوک والد خود گسترش یابد، اما برای همه بلوک های نسل در دسترس است :

{
    let scopedVariable = true;
    {
    console.log( scopedVariable );
    }
}
> true

مقدار یک متغیر اعلام شده را می توان از داخل یک بلوک نزول تغییر داد:

{
    let scopedVariable = false;
    {
    scopedVariable = true;
    }
    console.log( scopedVariable );
}
> true

یک متغیر جدید را می توان با let یا const در داخل یک بلوک نزول بدون خطا مقداردهی کرد، حتی اگر از همان شناسه متغیر در بلوک والد استفاده کند:

{
    let scopedVariable = false;
    {
    let scopedVariable = true;
    }
    console.log( scopedVariable );
}
> false

محدوده عملکرد

متغیرهای اعلام شده با استفاده از var به نزدیکترین تابع حاوی خود (یا بلوک اولیه سازی ایستا در یک کلاس ) محدوده می شوند.

function myFunction() {
    var scopedVariable = true;

    return scopedVariable;
}

scopedVariable;
> ReferenceError: scopedVariable is not defined

پس از فراخوانی یک تابع، این وضعیت همچنان ادامه دارد. حتی اگر متغیر در حین اجرای تابع مقداردهی اولیه شود، آن متغیر هنوز خارج از محدوده تابع در دسترس نیست:

function myFunction() {
    var scopedVariable = true;

    return scopedVariable;
}

scopedVariable;
> ReferenceError: scopedVariable is not defined

myFunction();
> true

scopedVariable;
> ReferenceError: scopedVariable is not defined

گستره جهانی

یک متغیر سراسری در کل یک برنامه جاوا اسکریپت، در داخل هر بلوک و توابع، برای هر اسکریپت موجود در صفحه موجود است.

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

هر متغیری که با استفاده از var در خارج از یک تابع والد یا با استفاده از let یا const خارج از بلوک والد اعلام شود، جهانی است:

var functionGlobal = true; // Global
let blockGlobal = true; // Global

{
    console.log( blockGlobal );
    console.log( functionGlobal );
}
> true
> true

(function() {
    console.log( blockGlobal );
    console.log( functionGlobal );
}());
> true
> true

اختصاص دادن یک مقدار به یک متغیر بدون اعلان صریح آن (یعنی با استفاده از var , let یا const برای ایجاد آن) یک متغیر را به دامنه جهانی ارتقا می دهد، حتی زمانی که در داخل یک تابع یا بلوک مقداردهی اولیه شود. متغیری که با استفاده از این الگو ایجاد می‌شود، گاهی اوقات «جهانی ضمنی» نامیده می‌شود.

function myFunction() {
    globalVariable = "global";

    return globalVariable
}

myFunction()\
> "global"

globalVariable\
> "global"

بالابر متغیر

متغیرها و اعلان‌های توابع در بالای محدوده خود قرار می‌گیرند، به این معنی که مفسر جاوا اسکریپت هر متغیری را که در هر نقطه از یک اسکریپت اعلام شده پردازش می‌کند و به طور موثر قبل از اجرای اسکریپت، آن را به اولین خط محدوده خود منتقل می‌کند. این بدان معنی است که متغیری که با استفاده از var اعلام شده است، می تواند قبل از اینکه متغیر اعلام شود بدون اینکه با خطا مواجه شود، ارجاع داده شود:

hoistedVariable
> undefined

var hoistedVariable;

از آنجا که فقط اعلان متغیر میزبانی می شود، نه مقداردهی اولیه، متغیرهایی که به صراحت با var ، let یا const اعلان نشده اند، بالا نمی روند:

unhoistedVariable;
> Uncaught ReferenceError: unhoistedVariable is not defined

unhoistedVariable = true;

همانطور که قبلا ذکر شد ، به یک متغیر اعلام شده اما بدون مقدار اولیه مقدار undefined اختصاص داده می شود. این رفتار برای اعلان های متغیر hoisted نیز اعمال می شود، اما فقط برای آنهایی که با استفاده از var اعلان شده اند.

hoistedVariable
> undefined

var hoistedVariable = 2 + 2;

hoistedVariable\
> 4

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

let و const این رفتار را با پرتاب خطا در هنگام دسترسی به متغیر قبل از ایجاد آن، برطرف کند:

{
    hoistedVariable;

    let hoistedVariable;
}
> Uncaught ReferenceError: can't access lexical declaration 'hoistedVariable' before initialization

این خطا با خطای "hoistedVariable is not defined" که ممکن است هنگام تلاش برای دسترسی به یک متغیر اعلام نشده انتظار داشته باشید متفاوت است. از آنجا که جاوا اسکریپت متغیر را افزایش داده است، آگاه است که متغیر در محدوده داده شده ایجاد می شود. با این حال، به جای اینکه آن متغیر را قبل از اعلان آن با مقدار undefined در دسترس قرار دهد، مفسر خطا می‌کند. متغیرهای اعلام شده با let یا const (یا class ) گفته می شود که در یک "منطقه مرده زمانی" ("TDZ") از ابتدای بلوک محصور خود تا نقطه ای از کد که متغیر در آن اعلان می شود وجود دارند.

منطقه مرده زمانی رفتار let را برای نویسندگان بصری تر از var می کند. همچنین برای طراحی const حیاتی است. از آنجایی که ثابت ها را نمی توان تغییر داد، ثابتی که در بالای محدوده آن قرار می گیرد و مقدار ضمنی undefined به آن داده می شود، نمی تواند با مقدار معنی دار مقداردهی اولیه شود.

درک خود را بررسی کنید

با چه نوع شخصیت هایی می توانید یک شناسه را شروع کنید؟

یک نامه
یک خط زیر
یک رقم

کدام روش ترجیحی برای اعلام متغیری است که مقدار آن در هر زمان قابل تغییر است؟

اجازه دهید
پایان
var