درآمدی بر برخی فیچرهای کمتر شناخته‌شدهٔ جاوااسکریپت

درآمدی بر برخی فیچرهای کمتر شناخته‌شدهٔ جاوااسکریپت

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

اپراتور void
یک اپراتور به اصطلاح Unary (تک‌منظوره) است که تنها برای اجرای دستور مد نظر بدون ریترن کردن مقداری از آن به کار گرفته می‌شود و مقدار undefined را در خروجی ریترن می‌کند برای مثال کدهای زیر را در نظر بگیرید:

void 0
void (0)

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

void(1 === 1);
void anyFunction();

در کد بالا دستور سطر اول یک مقایسۀ درست می‌باشد که دو عدد از نظر مقدار و نوع با هم برابر بوده و باید مقدار true در خروجی ریترن شود اما به دلیل استفاده از اپراتور void مقداری مبنی بر درست بودن این مقایسه در خروجی ریترن نخواهد شد. همان‌طور که در خط دوم مشاهده می‌شود، استفاده از این کیورد برای تعریف فانکشن‌ها نیز منجر بدین خواهد شد تا فانکشن مد نظر اجرا شده اما مقداری را در خروجی ریترن نکند (برای آشنایی با سایر اپراتورهای این زبان به مقالۀ درآمدی بر اپراتورها در زبان جاوااسکریپت مراجعه نمایید.)

اختیاری بودن پرانتز برای ساخت Object
پرانتزهایی که بعد از نام کلاس جهت ساخت یک آبجکت جدید می‌آوریم اختیاری هستند که بدین طریق در هنگام فراخوانی کانستراکتور می‌توانیم از پاس دادن آرگومان ورودی به آن خودداری کنیم. در همین راستا در ادامه سه نمونه کد معتبر در این زبان را هم با استفاده از پرانتز و هم بدون استفاده از آن آورده‌ایم:

const date = new Date();
const month = new Date().getMonth();
const myInstance = new MyClass();

همان‌طور که در کد فوق می‌بینید سه نمونه آبجکت ساخته‌ایم که در هر یک از آن‌ها نیز علائم () را به کار برده‌ایم اما در عین حال امکان تغییر دستورهای فوق‌الذکر را به صورت زیر داریم:

const date = new Date;
const month = (new Date).getMonth();
const myInstance = new MyClass;

هر یک از این دستورها نیز در زبان جاوااسکریپت معتبر بوده و به منزلۀ ساخت آبجکت جدید از کلاس‌های مد نظر هستند که البته وقتی علائم () درج نشوند نمی‌توان آرگومانی را به عنوان ورودی به کانستراکتور فراخوانی‌شده از کلاس مد نظر پاس داد.

عدم استفاده از پرانتز برای تعریف IIFE
IIFE مخفف عبارت Immediately Invoked Functional Expression بوده و به فانکشن‌هایی اشاره دارد که به صورت بی‌نام تعریف شده و به محض تعریف نیز اجرا می‌شوند که می‌توانیم آن‌ها را بدون پرانتزهای ابتدایی نیز تعریف کنیم. در ادامه، نمونه‌ای از سینتکس معتبر پیاده‌سازی یک به اصطلاح IIFE را آورده‌ایم:

(function (){
    console.log('Normal IIFE called')
}
)()

در کد فوق با استفاده از پرانتزهای ابتدایی به مفسر جاوااسکریپت گفته‌ایم که اسکریپت مد نظر یک دستور فانکشنال است و تحت هیچ عنوان فانکشنی نیست تا به محض تعریف اجرا گردد و در ادامه با به‌کارگیری کیورد function یک فانکشن بی‌نام تعریف کرده و گفته‌ایم در صورت اجرا، استرینگ «Normal IIFE called» در خروجی چاپ شود. حال اگر بخواهیم فانکشن بی‌نام فوق را بدون استفاده از پرانتزهای ابتدایی تعریف کنیم، خواهیم داشت:

void function (){
    console.log('Normal IIFE called')
}()

در کد فوق با حذف پرانتزهای ابتدایی، اپراتور void را برای تعریف فانکشن بی‌نام به کار گرفته‌ایم و بدین وسیله به مفسر جاوااسکریپت دستور می‌دهیم که کد مد نظر یک دستور فانکشنال است و به محض تعریف باید اجرا شود و از همین روی می‌توانیم از آوردن () در ابتدا خودداری کنیم اما همان‌طور که کمی قبل‌تر بیان کردیم، اپراتور void منجر بدین می‌شود که فانکشن بی‌نام فوق‌الذکر مقداری را در خروجی ریترن نکند که در صورت نیاز به ریترن شدن نتیجه می‌توان به جای استفاده از اپراتور void فانکشن مذکور را به یک متغیر دلخواه منتسب کرد که بدین ترتیب دیگر نیازی به آوردن پرانتزهای ابتدایی نخواهد بود و نتیجۀ حاصل از اجرای فانکشن در متغیر مذکور نگاه‌داری شده و می‌توانیم در صورت نیاز آن را مورد استفاده قرار دهیم که برای این منظور کدهای فوق را به صورت زیر ریفکتور کرده‌ایم:

result = (function () {
    return 'SokanAcademy.com'
})()

در کد فوق متغیری تحت عنوان result تعریف کرده و فانکشن بی‌نامی را به روش متداول و با استفاده از پرانتزهای ابتدایی تعریف کرده‌ایم که این وظیفه را دارا است تا استرینگ «SokanAcademy.com» را در خروجی ریترن کند و نتیجۀ حاصل از اجرای این فانکشن در متغیر result نگاه‌داری می‌شود اما اگر بخواهیم فانکشن بی‌نام فوق را بدون ذکر پرانتزهای ابتدایی تعریف کنیم، خواهیم داشت:

result = function () {
    return 'SokanAcademy.com'
}()

مجدداً در کد فوق فانکشن بی‌نام مد نظر را به متغیری تحت عنوان result منتسب کرده‌ایم که بدین ترتیب می‌توانیم از آوردن پرانتزهای ابتدایی برای تعریف فانکشن به اصطلاح IIFE خودداری کنیم و در نتیجۀ اجرای دستور فوق استرینگ زیر در خروجی ریترن خواهد شد:

SokanAcademy.com

استرینگ بالا نتیجۀ حاصل از اجرای دستور فانکشنال فوق‌الذکر بوده و در متغیر result نگاه‌داری می‌شود.

دستور ()Function
در زبان برنامه‌نویسی جاوااسکریپت استفاده از کیورد function تنها راه به منظور تعریف فانکشن‌ها نیست بلکه این زبان قابلیتی دارا است که در آن می‌توانیم با به‌کارگیری دستور ()Function با حرف اول بزرگ و به همراه کیورد new یک فانکشن جدید را تعریف کنیم:

var multiply = new Function("x", "y", "return x*y;");
multiply (2,3)

در کد فوق فانکشنی تحت عنوان ()multiply را با به‌کارگیری کیوردهای ()new Function تعریف کرده‌ایم بدین صورت که دو آرگومان ورودی x و y برای آن تعریف کرده و گفته‌ایم دستور x*y روی پارامترهای ورودی مد نظر اِعمال شود که در واقع آرگومان آخر به عنوان بدنۀ فانکشن مذکور خواهد بود. جهت تست نیز فانکشن ()multiply را با دو پارامتر ورودی 2 و 3 فراخوانی کرده‌ایم که نتیجۀ حاصل از اجرای آن، ریترن شدن عدد 6 در خروجی خواهد بود.

افزودن یکسری Property متناسب با نیاز اپلیکیشن به فانکشن‌ها
جاوااسکریپت یک زبان شیئ‌گرا است که در آن فانکشن‌ها نیز به عنوان آبجکت در نظر گرفته می‌شوند و بنابراین می‌توانیم ویژگی‌های مد نظر خود را به فانکشن‌ها اضافه کنیم. برای مثال، در ادامه قصد داریم فانکشنی تحت عنوان ()greet تعریف کنیم که به ازای شرایط مختلف، استرینگ‌های متفاوتی را در خروجی ریترن کند که در همین راستا داریم:

function greet() {
    if (greet.locale === 'fr') {
        console.log('Bonjour!')
    } else if (greet.locale === 'es') {
        console.log('Hola!')
    } else {
        console.log('Hello!')
    }
}

در کد فوق فانکشنی تحت عنوان ()greet تعریف کرده‌ایم و در آن آبجکتی به نام locale ساخته‌ایم که به ترتیب زیر عمل می‌کند:

- چنانچه مقدار استرینگ ورودی برای این آبجکت برابر با «fr» باشد، فانکشن مد نظر استرینگ «!Bonjour» را در خروجی چاپ می‌کند.
- اگر مقدار استرینگ ورودی را برابر با عبارت «es» قرار دهیم، فانکشن مد نظر استرینگ «!Hola» را در خروجی چاپ می‌کند.
- و در باقی شرایط نیز استرینگ «!Hello» در خروجی چاپ خواهد شد.

در ادامه فانکشن مذکور را فراخوانی می‌کنیم:

greet();
greet.locale = 'fr';
greet();

به طور کلی، نتیجۀ حاصل از اجرای دستورات فوق بدین ترتیب خواهد بود: 

Hello!
Bonjour!

همان‌طور که در کد فوق مشاهده می‌کنید، فانکشن ()greet در ابتدا بدون استرینگ ورودی فراخوانی شده است که منجر به اجرای دستور مربوط به else شده و استرینگ «!Hello» در خروجی چاپ می‌شود و در ادامه استرینگ ورودیِ «fr» را به آبجکت locale از فانکشن ()greet اختصاص داده‌ایم که منجر به چاپ استرینگ «!Bonjour» خواهد شد.

امکان تگ‌گذاری Template Literals
Template Literals در نسخۀ ES6 به این زبان افزوده شدند و با علائم به اصطلاح بَک‌کوتیشن یا ‍‍‍‍`` نشان داده می‌شوند که این امکان را در اختیار دولوپرها قرار می‌دهند تا استرینگ مد نظر خود را دقیقاً به همان صورت ورودی در خروجی چاپ کرده و همچنین قابلیت شناسایی و پردازش دستور مد نظر با به‌کارگیری علائم {}$ را برای ایشان فراهم می‌کنند به طوری که داریم:

var a = 5;
var b = 10;
console.log(`Fifteen is ${a + b} and
not ${2 * a + b}.`);

در کد بالا دو متغیر تحت عناوین a و b با مقادیر اولیۀ 5 و 10 تعریف کرده و در ادامه گفته‌ایم استرینگ فوق در خروجی چاپ شود که می‌بینیم به سادگی بخشی از استرینگ مد نظر در سطر بعد چاپ شده و دستورات مربوط به دو متغیر نیز با به‌کارگیری بک‌کوتیشن‌ها و همچنین علائم {}$ شناسایی و اجرا می‌شوند و در نهایت خروجی حاصل از اجرای این دستور به ترتیب زیر خواهد بود:

Fifteen is 15 and 
not 20.

همان‌طور که می‌بینید، استرینگ مد نظر به همان شکل ورودی در دو سطر مجزا پردازش شده و در خروجی چاپ می‌شود مضاف بر اینکه دستورات داخل علائم {}$ شناسایی شده و روی دو متغیر مذکور اِعمال شده‌اند.

همچنین لازم به یادآوری است که در نسخۀ جدید زبان برنامه‌نویسی جاوااسکریپت قابلیت تگ‌گذاری روی به اصطلاح Template Literal نیز فراهم شده است که این امکان را در اختیار دولوپرها قرار می‌دهد تا بتوانند یکسری پردازش‌ها روی استرینگ مد نظر و با استفاده از فانکشنی تحت عنوان تگ مذکور اِعمال کنند که برای این منظور مثال زیر را مد نظر قرار داده‌ایم:

function highlight(strings, ...values) {
    let result = ''
    strings.forEach((str, i) => {
        result += str
        if (values[i]) {
            result += `<mark>${values[i]}</mark>`
        }
    })
    return result
}
const author = 'Henry Avery'
const statement = `I am a man of fortune & I must seek my fortune`
const quote = highlight `${author} once said, ${statement}`
console.log(quote)

در این کد فانکشنی تحت عنوان ()highlight تعریف کرده‌ایم که دو آرگومان ورودی به نام‌های strings و values دارد که در ادامه کاربرد هر یک را به ترتیب بررسی می‌کنیم:

- متغیر strings قرار است تا آرایه‌ای از استرینگ‌های مد نظر برای چاپ در خروجی را ذخیره سازد.
- متغیر values مجموعه‌ای از آرگومان‌های ورودی را نگاه‌داری می‌کند که به عنوان استرینگ ورودی به فانکشن می‌دهیم و به آرایۀ فوق‌الذکر افزوده می‌شوند تا در استرینگ خروجی جای‌گذاری شده و چاپ شوند.

در واقع، طبق دستورات فوق در حال حاضر پارامترهای ورودی به فانکنشن ()highlight بدین صورت می‌باشند:

highlight([' ', 'once said', ' '], 'I am a man of fortune & I must seek my fortune', 'Henry Avery')

پارامتر اول آرایه‌ای از استرینگ‌های مد نظر برای چاپ در خروجی است که اِلِمان اول و سوم در حال حاضر خالی بوده و در ادامه دو استرینگ فوق را به عنوان ورودی به آن پاس داده‌ایم که می‌خواهیم به ترتیب به جای علائم {}$ جای‌گذاری شده و در خروجی چاپ شوند.

در تفسیر کد فوق باید بگوییم که فانکشن ()highlight را بدین صورت تعریف کرده‌ایم که در ابتدا متغیری به نام result تعریف کرده و مقدار اولیۀ آن را یک استرینگ خالی قرار داده‌ایم و در ادامه به ازای هر یک از عناصر آرایۀ strings متغیری به نام i تعریف کرده‌ایم تا بتوانیم هر یک از عناصر آرایۀ مذکور تحت عنوان str را پیمایش کنیم که بدین ترتیب هر یک از آن‌ها را برداشته و به متغیر result اضافه می‌کنیم و گفته‌ایم تا زمانی که اِلِمانی داخل متغیر values (استرینگ‌های ورودی به تابع مد نظر) وجود داشته باشد، آن‌ها را به ترتیب برداشته و در متغیر result داخل تگ‌های <mark></mark> جای‌گذاری کند و در نهایت مقادیر استرینگ‌های ورودی و استرینگ تعریف‌شده در متغیر strings با یکدیگر کانکت شده و استرینگ نهایی در خروجی ریترن می‌شود.

به منظور فراخواننی فانکشن ()highlight دو متغیر تحت عناوین author و statement تعریف کرده و استرینگ‌های فوق را به آن‌ها اختصاص داده‌ایم و در ادامه متغیری دیگر تحت عنوان quote تعریف می‌کنیم که قرار است تا نتیجۀ حاصل از اجرای فانکشن ()highlight در آن نگاه‌داری شود که بدین ترتیب فانکشن ()highlight فراخوانی شده و در آن گفته‌ایم هر یک از استرینگ‌های زیر به ترتیب در آرایۀ strings نگاه‌داری شوند:

' ' //null string
'once said'
' ' //null string

در ادامه هر یک از استرینگ‌های موجود در متغیرهای author و statement به متغیر values داده شده و به ترتیب به جای دستورهای {author}$ و {statement}$ جای‌گذاری می‌شوند و در نهایت استرینگ ذخیره‌شده در متغیر quote چاپ می‌شود که در خروجی استرینگ زیر را خواهیم داشت:

<mark> Henry Avery </mark> once said, <mark>I am a man of fortune & I must seek my fortune</mark>

همان‌طور که مشاهده می‌کنید، استرینگ‌های ورودی داخل تگ‌های <mark></mark> قرار گرفته و با استرینگ تعریف‌شده کانکت شده‌اند.

کیوردهای get و set
دسترسی به پراپرتی‌های مربوط به آبجکت‌های تعریف‌شده در زبان جاوااسکریپت بسیار ساده است. برای مثال، اگر آبجکتی فرضی تحت عنوان user داشته باشیم که یکی از پراپرتی‌های آن را age تعریف کنیم، بدین ترتیب دسترسی به پراپرتی مذکور با دستور user.age امکان‌پذیر خواهد بود که مقدار اختصاص‌یافته به پراپرتی مد نظر را به دست خواهیم آورد یا اگر چنانچه آبجکت user یک پراپرتی تحت عنوان age نداشته باشد، مقدار undefined در خروجی ریترن خواهد شد.

فیچرهایی تحت عنوان get و set در جاوااسکریپت این امکان را برای دولوپرها فراهم می‌کنند تا بتوانند به ترتیب یک فانکشن به اصطلاح Getter تعریف کرده و مقادیر مد نظر خود از آبجکت مذکور را در خروجی ریترن کنند و همچنین با تعریف یک فانکشن Setter نیز می‌توان یکسری پراپرتی جدید برای آبجکت مذکور تعریف کرده و مقادیری منحصربه‌فرد برای آن‌ها به اصطلاح سِت کرد:

const user = {
        firstName: 'Ali',
        lastName: 'Azad',
        get fullName() {
            return this.firstName + ' ' + this.lastName
        },
        set age(value) {
            if (isNaN(value)) throw Error('Age has to be a number')
            this.tmpAge = Number(value)
        },
        get age() {
            return this.tmpAge
        }
    }

همان‌طور که در کد فوق می‌بینید، آبجکتی تحت عنوان user ایجاد کرده و در ادامه یکسری پراپرتی به نام‌های firstName و lastName برای آن تعریف کرده‌ایم که به ترتیب نام و نام خانوادگی کاربر را نگاه‌داری می‌کنند و در ادامه با به‌کارگیری کیورد get فانکشنی تحت عنوان ()fullName تعریف می‌کنیم که خود در نقش یک پراپرتی برای آبجکت مذکور خواهد بود و بدین ترتیب گفته‌ایم مقادیری را نگاه‌داری کند که مربوط به پراپرتی‌های firstName و lastName هستند و این مقادیر با قرار دادن یک فاصله مابین آن‌ها با یکدیگر کانکت شده و به عنوان مقدار پراپرتی fullName در خروجی ریترن شود که از این پس مقدار پراپرتی fullName برابر با نام و نام خانوادگی کاربر خواهد بود.

حال قصد داریم تا پراپرتی جدیدی به آبجکت user تحت عنوان age بیفزاییم که برای این منظور فانکشنی تحت عنوان ()age با به‌کارگیری کیورد set تعریف می‌کنیم که خود در نقش پراپرتی مذکور می‌باشد و یک آرگومان ورودی تحت عنوان value به آن داده و در ادامه گفته‌ایم اگر چنانچه مقدار متغیر value (پارامتر ورودی به این فانکشن) از نوع عدد نبود، اروری در قالب استرینگ «Age has to be a number» در خروجی چاپ شود و در ادامه گفته‌ایم مقدار پارامتر ورودی که حتماً از نوع عدد می‌باشد را به متغیری تحت عنوان tmpAge اختصاص دهد که در سطر بعد با به‌کارگیری کیورد get گفته‌ایم فانکشن ()age که به عنوان یک پراپرتی تحت عنوان age برای آبجکت user می‌باشد، مقدار ذخیره‌شده در متغیر tmpAge را ریترن کند.

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

console.log(user.fullName)
user.firstName = 'Morteza'
console.log(user.fullName)
user.age = '27'
console.log(user.age)
user.age = 'Twenty Seven'

در دستور اول گفته‌ایم مقدار پراپرتی fullName از آبجکت user در خروجی چاپ شود که مفسر جاوااسکریپت به دنبال پراپرتی مذکور در آبجکت user می‌گردد که در فانکشن ()fullName از نوع get گفته‌ایم مقدار معادل برای این پراپرتی، استرینگ کانکت‌شده از مقادیر مربوط به دو پراپرتی firstName و lastName می‌باشد و بنابراین عبارت زیر در خروجی چاپ می‌شود:

Ali Azad

دستور سطر دوم مقدار پراپرتی firstName از آبجکت user را به استرینگ «Morteza» تغییر می‌دهد که بدین ترتیب عبارت «Morteza Azad» به پراپرتی fullName اختصاص یافته و دستور سطر سوم استرینگ زیر را در خروجی چاپ می‌کند:

Morteza Azad

در دستور سطر چهارم نیز گفته‌ایم عدد 27 به پراپرتی جدید age اختصاص یافته و در ادامه مقدار آن در خروجی چاپ می‌شود و در سطر آخر نیز استرینگ «Twenty Seven» را به پراپرتی age اختصاص می‌دهیم که با توجه به شرط مطرح‌شده در فانکشن مربوط به این پراپرتی تحت عنوان ()age گفته‌ایم مقدار ورودی برای این پراپرتی حتماً باید از نوع عدد باشد و از همین روی اجرای دستور فوق منجر به ایجاد اروری در قالب استرینگ زیر می‌شود:

Uncaught Error: Age has to be a number

بدین ترتیب با استفاده از قابلیت به اصطلاح set و get در این زبان می‌توانیم پراپرتی‌های مد نظر از آبجکتی را در خروجی ریترن کرده و همچنین در صورت نیاز یکسری پراپرتی برای آبجکت خود تعریف کنیم.

اپراتور Comma
اپراتور کاما با علامت , در زبان برنامه‌نویسی جاوااسکریپت یکسری فیچرهایی در اختیار دولوپرها قرار می‌دهد که در ادامه هر یک از آن‌ها را بررسی می‌کنیم.

فیچر اول بدین صورت است که با استفاده از کاما می‌توانیم نتیجۀ حاصل از اجرای چند دستور متفاوت را به یک متغیر منتسب کنیم که در نهایت نتیجۀ ریترن‌شده از اجرای دستور آخر در متغیر مذکور نگاه‌داری خواهد شد به طوری که در یک حالت کلی داریم:

let result = expression1, expression2, ... expression N

در شبه‌کد فوق نتیجۀ ریترن‌شده از اجرای دستور شمارۀ N در متغیری به نام result نگاه‌داری می‌شود.

قابلیت بعدی برای اپراتور کاما جدا کردن یکسری به اصطلاح Statement مربوط به حلقۀ تکرار for می‌باشد که یک مثال از آن در ادامه بررسی می‌شود:

for (var a = 0, b = 10; a <= 10; a++, b--)

در دستور فوق گفته‌ایم به ازای دو متغیر a و b با مقادیر اولیۀ 0 و 10 دستورات فرضی داخل بلوک for اجرا شوند و در هر مرتبه اجرای آن‌ها هم یک واحد به متغیر a اضافه شده و هم یک واحد از مقدار متغیر b کم شود و اجرای دستورات داخل حلقه نیز تا زمانی ادامه یابد که مقدار متغیر a کوچک‌تر یا مساوی با عدد 10 می‌شود.

فیچر دیگری در مورد علامت , به‌کارگیری آن برای جدا کردن دستوراتی است که می‌خواهیم به صورت خلاصه و در یک سطر نوشته شوند که برای مثال داریم:

function getNextValue() {
    return counter++, console.log(counter), counter
}

در این کد فانکشنی فرضی تحت عنوان ()getNextValue تعریف کرده‌ایم که در صورت اجرا مقدار مربوط به متغیر فرضی counter را یک واحد افزایش داده و در خروجی ریترن می‌کند و در ادامه مقدار آن را در خروجی چاپ می‌کند که دستور سوم نیز مجدداً منجر به ریترن شدن مقدار موجود در متغیر counter در خروجی می‌شود که اکنون یک واحد افزایش پیدا کرده است.

اپراتور Plus
اپراتور + پیش از استرینگ مد نظر آمده و به منظور تبدیل دیتا تایپ استرینگ به دیتا تایپ عددی مورد استفاده قرار می‌گیرد بدین صورت که اگر قبل از هرگونه استرینگی ذکر شود، دیتا تایپ آن به نوع دادۀ عددی تغییر می‌یابد:

typeof('9.11')
typeof(+'9.11')

در دستور سطر اول با به‌کارگیری کیورد typeof نوع دادۀ عبارت '9.11' را در خروجی ریترن می‌کنیم که string است اما همان‌طور که می‌بینید در دستور سطر بعد با استفاده از اپراتور + نوع دادۀ استرینگ مذکور را به عدد تغییر داده‌ایم و نتیجۀ ریترن شده از آن عبارت number خواهد بود.

اپراتور Double Bang
در زبان برنامه‌نویسی جاوااسکریپت اپراتور ! به NOT منطقی اشاره می‌کند و مقدار بولین برای عبارت مد نظر را معکوس می‌کند که با به‌کارگیری آن مقادیر بولین true به false و برعکس تبدیل می‌شوند و از همین روی اپراتور !! که تحت عنوان Double Bang نیز شناخته می‌شود به معنای معکوس کردن اثر NOT منطقی بوده و بدین صورت عمل می‌کند که در ابتدا مقدار بولین عبارت مد نظر را معکوس کرده و در ادامه مقدار حاصل را مجدداً معکوس می‌کند. برای مثال در دستور زیر داریم:

const x = '';
!!x;

در کد فوق متغیری به نام x تعریف کرده و مقدار استرینگ خالی را به آن داده‌ایم و از آنجایی که مقدار بولین برای یک استرینگ خالی برابر false می‌باشد، در ادامه گفته‌ایم مقدار بولین برای این متغیر دو مرتبه معکوس شود که در ابتدا منجر به true شدن متغیر x و در مرحلۀ بعد منجر به false شدن مقدار بولین آن می‌گردد که در نهایت عبارت false برای متغیر مذکور در خروجی ریترن می‌شود. به عنوان یک مثال دیگر داریم:

!!null

لازم به یادآوری است که مقدار بولین برای کیورد null برابر با false می‌باشد که در طی دو مرتبه معکوس‌سازی آن ابتدا به مقدار true و در مرحلۀ بعد مجدداً به مقدار بولین false تغییر می‌یابد.

قابلیت لیبل‌گذاری Statements
در یکی دیگر از فیچرهای جدید زبان برنامه‌نویسی جاوااسکریپت امکانی برای دولوپرها فراهم شده است که در آن می‌توان برخی بلوک‌های کد و یا حلقه‌های تکرار مد نظر خود را به اصطلاح لِیبل‌گذاری کرد که بدین ترتیب با به‌کارگیری دستورهای break و یا continue به قطعه کد مد نظر دسترسی داریم و به منظور تسهیل هندل کردن حلقه‌های تودرتو مورد استفاده قرار می‌گیرد که در همین راستا مثال زیر را در ادامه بررسی می‌کنیم:

First: for (var i = 0; i < 3; i++) {
        Second: for (var j = 0; j < 3; j++) {
            if (i === 1) continue First;
            if (j === 1) break Second;
            console.log(i);
            console.log(j);
        }
    }

در کد فوق لیبلی تحت عنوان First برای حلقۀ اول و لیبلی دیگر تحت عنوان Second برای حلقۀ دوم در نظر گرفته‌ایم و در ادامه گفته‌ایم هر دو حلقه سه مرتبه اجرا شوند که مراحل مذکور بدین صورت خواهند بود:

در ابتدا مقدار متغیر i و j برابر با 0 بوده و هیچ یک از دستورات شرطی اول و دوم برقرار نیستند که در مرحلۀ اول دو عدد 0 در خروجی چاپ خواهند شد. در مرحلۀ بعد مقدار متغیر i همچنان 0 بوده و حلقۀ داخلی یک واحد متغیر j را افزایش می‌دهد که اکنون مقادیر زیر را برای دو متغیر i و j داریم:

i = 0
j = 1

در نتیجه شرط دوم برقرار شده و با اجرای دستور ;break Second مفسر از حلقۀ داخلی خارج می‌شود و به اجرای حلقۀ First می‌پردازد و بدین ترتیب مقدار متغیر i یک واحد افزایش یافته و شرط اول برقرار می‌شود و با اجرای دستور ;continue First گفته‌ایم چنانچه مقدار متغیر i برابر با عدد 1 باشد، حلقه از ابتدا اجرا شود بدین معنی که ادامۀ دستور اجرا نشده و مفسر از ابتدا کد را اجرا می‌کند و از همین روی عدد 1 تحت هیچ عنوان در خروجی چاپ نمی‌شود که اکنون مقادیر دو متغیر i و j به ترتیب زیر خواهند بود:

i = 1
j = 0

که در مرحلۀ بعد مجدداً حلقۀ First مقدار متغیر i را یک واحد افزایش می‌دهد و در نتیجه مقدار دو متغیر i و j به ترتیب زیر خواهند بود:

i = 2
j = 0

در ادامه شرط اول و دوم چک می‌شود که هیچ یک برقرار نبوده و مفسر به سراغ اجرای سطرهای بعدی می‌رود که در این مرحله دستورات مربوط به چاپ مقادیر دو متغیر i و j اجرا شده و دو عدد 2 و 0 به ترتیب در خروجی چاپ می‌شوند. به طور کلی خروجی حاصل به صورت زیر خواهد بود:

0
0
2
0

همان‌طور که می‌بینید مقدار عدد 1 از متغیر i هرگز چاپ نشده و حلقۀ Second نیز تنها یک مرتبه اجرا شده و در مرحلۀ بعد مفسر جاوااسکریپت از حلقۀ مذکور خارج می‌شود که بدین ترتیب مقدار متغیر j همچنان 0 باقی می‌ماند.

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

از بهترین نوشته‌های کاربران سکان آکادمی در سکان پلاس


online-support-icon