برنامه نویسی ۱۶۴ بازدید

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

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

اگر فاصله دورتری را دیده‌ام با ایستادن بر شانه‌های غول‌ها بوده است.

– نیوتن

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

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

// the family class is going to behave as tho
// its a JavaScript array internally so we can leverage
// the functionality of JavaScript arrays
class Family {
    constructor() {
        // Arrays have a length prop so we should too!
        this.length = 0;
    }

    addFamilyMember = (name) => {
        // We are an array so we can push to ourselves by setting the context
        Array.prototype.push.call(this, name);
    }

    findFamilyMember = (callback) => {
        return [].find.call(this, callback);
    }

    removeFamilyMember = () => {
        [].pop.call(this);
    }

    // list all properties on our object that are not a function
    listProps = (fn) => {
        Object.keys(this).forEach(key => {
            if (typeof this[key] !== 'function') {
                fn(this[key]);
            }
        });
    }
}

در کد فوق کلاسی داریم که نمایش‌دهنده خانواده خواهد بود. چنان که متوجه شده‌اید ما هیچ آرایه‌ای در هیچ جای کد نساخته‌ایم. در واقع قصد داریم با کلاس Family خود مانند یک آرایه رفتار کنیم.

در خط درون سازنده می‌بینید که یک مشخصه length اضافه کرده‌ایم. ارائه‌ها دارای مشخصه length هستند و از این رو ما نیز باید چنین عمل کنیم.

در خط 10 کد فوق تابع ()addFamilyMember را داریم. این تابع نام عضو خانواده را می‌گیرد و آن را به آرایه اضافه می‌کند. اما ما هیچ آرایه‌ای ایجاد نکرده‌ایم!

در خط 12 متد ()push را روی آرایه از طریق ()call فراخوانی می‌کنیم. ()call به ما امکان می‌دهد که چارچوبی که می‌خواهیم تابع در آن اجرا شود را تعیین کنیم. در این حالت این را روی شیء family به صورت context تنظیم می‌کنیم.

نکته: «چارچوب تابع» (Function context) در جاوا اسکریپت یک موضوع مهم محسوب می‌شود. این چارچوب برای هر تابع جاوا اسکریپت بسته به این که تابع چگونه فراخوانی می‌شود متفاوت خواهد بود. روش‌های مختلفی برای فراخوانی یک تابع در جاوا اسکریپت وجود دارد که ()call و ()apply تنها دو مورد از آن‌ها هستند. اینک کنسول را باز کنید، یک وهله جدید از Family بسازید و عضو خانواده را اضافه کنید تا ببینیم چه به دست می‌آید:

قابلیت های جاوا اسکریپت در اشیای سفارشی

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

در ادامه تست‌های بیشتری اجرا می‌کنیم تا ببینیم چه به دست می‌آید. در کد زیر چند تست را می‌بینید:

// the family class is going to behave as tho
// its a JavaScript array internally so we can leverage
// the functionality of JavaScript arrays
class Family {
    constructor() {
        // Arrays have a length prop so we should too!
        this.length = 0;
    }

    addFamilyMember = (name) => {
        // We are an array so we can push to ourselves by setting the context
        Array.prototype.push.call(this, name);
    }

    findFamilyMember = (callback) => {
        return [].find.call(this, callback);
    }

    removeFamilyMember = () => {
        [].pop.call(this);
    }

    // list all properties on our object that are not a function
    listProps = (fn) => {
        Object.keys(this).forEach(key => {
            if (typeof this[key] !== 'function') {
                fn(this[key]);
            }
        });
    }
}


// a function to print to the console
let theConsole = function (member) { console.log(member) }

console.group('initial setup and load with Array.push')
//lets take the family class out for a spin
let f = new Family()
f.addFamilyMember('alex')
f.addFamilyMember('dana')
f.addFamilyMember('evan')
f.listProps(theConsole)
console.groupEnd()

console.group('find a family member using Array.find')
//lets find alex
let found = f.findFamilyMember(member => member === 'alex')
console.log(`we found ${found} by using Arrays own find method`)
console.groupEnd()


console.group('remove a family member using Array.pop')
f.removeFamilyMember()
f.listProps(theConsole)
console.groupEnd()

console.log(f)

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

قابلیت های جاوا اسکریپت در اشیای سفارشی

بدین ترتیب با موفقیت از push pop و find در این مثال استفاده کردیم. همچنین می‌توانید از هر تابعی که دوست دارید استفاده کنید. چنان که می‌بینید زمانی که نام‌های جدید به آرایه push می‌شوند، به مشخصه‌های شیء ما اضافه می‌شوند و کلید آن‌ها نیز روی اندیس‌هایی با آغاز از صفر تعیین می‌شوند.

اگر از تابع‌های داخلی آرایه استفاده کنید، مشخصه length دقیقاً مانند یک آرایه واقعی به صورت خودکار به‌روزرسانی می‌شود. اما اگر مسیر آرایه را ترک کنید و بخواهید شیء را با روش‌های دیگری دستکاری کنید، باید مشخصه length را خودتان به‌روز نگه دارید.

در نهایت این یک روش زیبا برای بهره‌گیری از کدهای موجود جاوا اسکریپت جهت بهبود اشیا محسوب می‌شود.

سخن پایانی

در این بخش برخی نکات مهم را مرور می‌کنیم.

  1. اگر مجبور نیستید، چرخ را از نو اختراع نکنید. هر زمان که مقدور است از مزیت کدهای کاملاً تست شده بهره بگیرید. بر شانه‌های غول‌ها بایستید.
  2. به دنبال کارکردهای مورد نظر خود در جاوا اسکریپت بگردید، زیرا این زبان امکان تعیین چارچوب تابع را فراهم ساخته است.
  3. ()call و ()apply دو مورد از متدهایی هستند که در هر تابعی قابل اجرا هستند. از آن‌ها بیشتر استفاده کنید.
  4. زمانی که شیئی مانند آن چه در این مقاله مطرح شد را پیاده‌سازی می‌کنید، تلاش کنید از API نیتیو بهره بگیرید، چون از عوارض جانبی هیچ حالت خاصی متضرر نخواهید شد. مثلاً دیگر مشکلی با عدم به‌روزرسانی صحیح مشخصه length نخواهید داشت.

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

==

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

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