• یک تابع جاوا اسکریپت که بیشترین مقدار را برمی گرداند. جاوا اسکریپت: توابع

    آخرین به روز رسانی: 04/09/2018

    توابع مجموعه ای از دستورالعمل ها هستند که یک عمل خاص را انجام می دهند یا مقدار خاصی را محاسبه می کنند.

    نحو تعریف توابع:

    تابع function_name([پارامتر [، ...]])( // دستورالعمل ها)

    تعریف تابع با کلمه کلیدی تابع و به دنبال آن نام تابع شروع می شود. نام تابع از قوانین یکسانی مانند نام متغیر پیروی می کند: فقط می تواند شامل اعداد، حروف، زیرخط و علامت دلار ($) باشد و باید با یک حرف، زیرخط یا علامت دلار شروع شود.

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

    بیایید ساده ترین تابع را تعریف کنیم:

    تابع display() (document.write("function in JavaScript"); )

    این تابع display() نامیده می شود. هیچ پارامتری نمی گیرد و تنها کاری که انجام می دهد نوشتن یک رشته در صفحه وب است.

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

    نیازی به دادن نام خاصی به توابع نیست. می توانید از توابع ناشناس استفاده کنید:

    Var display = function()( // تعریف تابع document.write("function JavaScript"); ) display();

    در واقع متغیر نمایشگر را تعریف می کنیم و به آن یک مرجع تابع اختصاص می دهیم. و سپس تابع با نام متغیر فراخوانی می شود.

    همچنین می توانیم به صورت پویا توابع را به یک متغیر اختصاص دهیم:

    Function goodMorning()( document.write("صبح بخیر"); ) function goodEvening()( document.write("عصر بخیر"); ) var message = صبح بخیر; message(); // پیام صبح بخیر = عصر بخیر; message(); // عصر بخیر

    پارامترهای تابع

    پارامترهای عبور را در نظر بگیرید:

    نمایش تابع (x)( // تعریف تابع var z = x * x; document.write (x + "معادل " + z)؛ ) display(5); // فراخوانی تابع

    تابع نمایش یک پارامتر، x را می گیرد. بنابراین، هنگام فراخوانی یک تابع، می توانیم مانند این مورد، یک مقدار برای آن ارسال کنیم، مثلاً عدد 5.

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

    تابع sum(a, b, c)( اجازه دهید d = a + b + c; console.log(d)؛ ) sum(1, 2, 3); اجازه دهید اعداد = ; مجموع (...عدد);

    در حالت دوم، اعداد از آرایه nums به تابع ارسال می شوند. اما برای انتقال نه تنها یک آرایه، به عنوان یک مقدار، بلکه دقیقاً اعداد از این آرایه، از عملگر spread (بیضی ...) استفاده می شود.

    پارامترهای اختیاری

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

    نمایش تابع (x, y)( if(y === تعریف نشده) y = 5؛ if(x === تعریف نشده) x = 8؛ اجازه دهید z = x * y؛ console.log(z)؛ ) نمایش () ; // نمایشگر 40 (6); // نمایش 30 (6، 4) // 24

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

    راه دیگری برای تعریف یک مقدار برای پارامترهای پیش فرض وجود دارد:

    نمایش تابع (x = 5، y = 10)( اجازه دهید z = x * y; console.log(z)؛ ) display(); // نمایشگر 50(6); // نمایشگر 60 (6، 4) // 24

    اگر هیچ مقداری به پارامترهای x و y ارسال نشود، به ترتیب به عنوان مقادیر 5 و 10 به دست می آیند. این روش مختصرتر و شهودی تر از مقایسه با روش تعریف نشده است.

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

    نمایش تابع (x = 5، y = 10 + x)( اجازه دهید z = x * y؛ console.log(z)؛ ) display(); // نمایش 75 (6); // نمایشگر 96 (6، 4) // 24

    در این حالت مقدار پارامتر y به مقدار x بستگی دارد.

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

    تابع display()( var z = 1; for(var i=0; i

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

    تعداد پارامترهای نامشخص

    با استفاده از عملگر spread، می توانیم نشان دهیم که تعداد متغیری از مقادیر را می توان با استفاده از یک پارامتر ارسال کرد:

    نمایش عملکرد (فصل، ... دما) (console.log(season); for(index in temps)(consol.log(temps);) ) display("Spring"، -2، -3، 4، 2، 5)؛ نمایش ("تابستان"، 20، 23، 31)؛

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

    خروجی کنسول:

    بهار -2 -3 4 2 5 تابستان 20 23 31

    نتیجه عملکرد

    یک تابع می تواند یک نتیجه را برگرداند. برای این منظور از عبارت return استفاده می شود:

    متغیر = 5; varz = مربع (y); document.write(y + " مربع برابر است " + z); تابع مربع (x) (برگردان x * x؛ )

    عبارت return با مقداری که از متد برگردانده می شود، دنبال می شود. در این مورد، مربع x است.

    پس از بدست آوردن نتیجه تابع، می توانیم آن را به متغیر دیگری نسبت دهیم:

    ورز = مربع (y);

    به عنوان پارامتر عمل می کند

    توابع می توانند به عنوان پارامترهای دیگر توابع عمل کنند:

    مجموع تابع (x, y)( بازگشت x + y; ) تابع تفریق (x, y) (بازگشت x - y؛ ) عملیات تابع (x, y, func) ( نتیجه var = func (x, y)؛ کنسول. log(نتیجه); ) کنسول log("Sum"); عملیات (10, 6, sum); // 16 console.log("Subtract"); عملیات (10، 6، تفریق)؛ // 4

    تابع عملیات سه پارامتر دارد: x، y و func. func - یک تابع را نشان می دهد، و در زمان تعریف عملیات، مهم نیست که چه نوع تابعی خواهد بود. تنها چیزی که می‌دانیم این است که تابع func می‌تواند دو پارامتر بگیرد و مقداری را برگرداند که سپس در کنسول مرورگر نمایش داده می‌شود. بنابراین می توانیم توابع مختلفی را تعریف کنیم (مانند توابع جمع و تفریق در این مورد) و آنها را به فراخوانی تابع عملیات منتقل کنیم.

    برگرداندن یک تابع از یک تابع

    یک تابع می تواند تابع دیگری را برگرداند:

    منوی تابع(n)( if(n==1) تابع برگردان (x, y)( x+y;) other if(n==2) تابع برگردان (x, y)( بازگشت x - y;) else if(n==3) تابع return(x, y)( return x * y;) return undefined; ) for(var i=1; i< 5; i++){ var action = menu(i); if(action!==undefined){ var result = action(5, 4); console.log(result); } }

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

    مقاله در حال توسعه!

    مقاله ای که در آن ما عملکرد چیست و همچنین نسخه سنتی (کلاسیک) کار با آن را در نظر می گیریم. علاوه بر این، آرگومان ها (پارامترهای) تابع و عبارت بازگشتی را تجزیه و تحلیل خواهیم کرد.

    تابع چیست؟

    یک تابع مقداری است مجموعه دستورالعمل، که می توان نام برد و سپس او را با این نام خطاب کنیداز هر کجای برنامه

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

    چگونه با استفاده از توابع، اجرای برخی وظایف را در جاوا اسکریپت سازماندهی کنیم؟ برای انجام این کار، معمولاً چنین کاری انجام می دهید:

    • تکلیف را به اجزای سازنده تقسیم کنید (وظایف فرعی)؛
    • وظایف فرعی از طریق توابع رسمیت می یابد.
    • کد اصلی را با استفاده از فراخوانی توابع ایجاد شده توسعه دهید.

    در نتیجه، چنین برنامه ای ساختارمندتر می شود. ایجاد تغییرات مختلف و افزودن ویژگی های جدید به آن آسان تر است.

    اعلام و فراخوانی یک تابع

    عملیات تابع در جاوا اسکریپت را می توان به 2 مرحله تقسیم کرد:

    • اعلام (ایجاد)کارکرد.
    • فراخوانی (اجرا)این تابع

    اعلام عملکردایجاد یک تابع در جاوا اسکریپت با نوشتن کلمه کلیدی تابع و به دنبال آن نام تابع و در صورت لزوم یک x داخل پرانتز شروع می شود. پارامترها ذکر شده است، به دنبال دستورالعمل هایی که محصور در براکت های مجعد.

    // اعلان تابع someName تابع someName() ( هشدار ("شما تابع someName را نامیدید!")؛ ) جاوا اسکریپت - نحو اعلان تابع

    توابع از این نوع در جاوا اسکریپت نامیده می شوند بیانیه عملکرد. علاوه بر این نوع، جاوا اسکریپت بین توابع نیز تمایز قائل می شود بیان تعریف تابعو عبارت تابع فلش .

    ترکیب نام تابع از قوانینی مشابه با نام متغیر پیروی می کند. آن ها می تواند شامل حروف، اعداد (0-9)، "$" و "_" باشد. توصیه می شود فقط از حروف الفبای انگلیسی (a-z، A-Z) به عنوان حروف استفاده کنید. نام تابع، مانند نام متغیر، نمی تواند با یک عدد شروع شود.

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

    مجموعه دستورالعملکد تابعی است که هنگام فراخوانی آن اجرا می شود.

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

    // تابع داده شده در مثال قبلی SomeName(); جاوا اسکریپت - تابع فراخوانی نحو

    آیا یک تابع در جاوا اسکریپت یک شی است؟

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

    // اعلان تابع someName تابع someName() ( هشدار("شما تابع someName را نامیدید!")؛ var reference = someName;

    پس از آن، می توانید تابع را به این صورت فراخوانی کنید:

    ارجاع()؛

    پارامترها و آرگومان های تابع

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

    // فراخوانی تابع sayWelcome با دو آرگومان ارسال شده به آن sayWelcome("Ivan", "Ivanov"); // یک فراخوانی دیگر به تابع sayWelcome با دو آرگومان sayWelcome("Peter", "Petrov");

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

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

    // اعلان تابع sayWelcome که دارای دو پارامتر تابع sayWelcome است (userFirstName، userLastName) ( // دستورالعملی که مقادیر پارامترهای "userFirstName" و "userLastName" را به کنسول console.log ("Welcome" نشان می دهد. + userLastName + " " + userFirstName );)

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

    برای مثال، بیایید تابع را از مثال بالا، بدون تعیین یک و دو پارامتر فراخوانی کنیم:

    // فراخوانی تابع sayWelcome و ارسال یک آرگومان به آن sayWelcome("Peter"); // خوش آمدید، پیتر تعریف نشده // فراخوانی تابع sayWelcome بدون ارسال آرگومان به آن sayWelcome(); // خوش آمدید undefined undefined

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

    // تابع اعلان تابع outputParam(param1, param2, param3) ( console.log(param1 + "; " + param2 + "; " + param3); ) // تابع outputParam را فراخوانی می کند که تعداد متفاوتی از پارامترها را به آن ارسال می کند outputParam(" باران" "برف"، "مه")؛ // باران؛ برف؛ mist outputParam(17); // 17; تعریف نشده؛ خروجی تعریف نشدهParam(24,33); // 24; 33; outputParam(); // تعریف نشده تعریف نشده؛ تعریف نشده

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

    // اعلان تابع مجموع تابع sum(num1, num2) ( /* num1 یا آرگومانها - مقدار 1 آرگومان num2 یا آرگومانها را بدست آورید - مقدار 2 آرگومان را بدست آورید */ var sum1 = num1 + num2, sum2 = آرگومانها + آرگومانها; بازگشت "Sum, مجموع بدست آمده توسط روش 1 " + sum1 + " است؛ مجموع به دست آمده توسط روش 2 " + sum2; ) /* خروجی نتیجه تابع sum به کنسول 7 - اولین آرگومان (می توان هم با نام num1 و هم با استفاده از آرگومان ها قابل دسترسی است) 4 - آرگومان دوم (هم با نام num2 و هم با آرگومان قابل دسترسی است) */ console.log(sum(7,4));

    تفاوت اصلی بین این روش ها این است که روش اول به شما امکان می دهد فقط به آن آرگومان هایی مراجعه کنید که در مرحله اعلان تابع نام داده شده اند. روش دوم به شما امکان می دهد مقدار هر آرگومان را حتی اگر نامی نداشته باشد (براساس شماره سریال) بدست آورید. این ویژگی زبان جاوا اسکریپت به شما امکان ایجاد توابع انعطاف پذیر جهانی را می دهد.

    علاوه بر دریافت آرگومان ها، شیء آرگومان ها به شما امکان می دهد تعداد آنها را نیز بیابید. این کار با استفاده از ویژگی length انجام می شود.

    تکرار بیش از استدلالبه یک تابع منتقل می شود، برای مثال، با استفاده از حلقه for یا for...of.

    // اعلان تابع sum تابع sum() ( var i = 0; console.log ("خروجی همه آرگومان ها با استفاده از حلقه for")؛ برای (i; i< arguments.length; i++) { console.log(i + 1 + " аргумент равен " + arguments[i]); } console.log("Вывод всех аргументов с помощью цикла for...of"); for (arg of arguments) { console.log(arg); } } // вызов функции sum sum(7, 4, 3, 1);

    تابعی که تمام آرگومان های ارسال شده به کنسول و تعداد آنها را در کنسول چاپ می کند:

    // تابع اعلان تابع myFunction () ( var i; console.log("تعداد پارامترهای ارسال شده =" + arguments.length); // تکرار روی همه پارامترها با استفاده از حلقه for برای (i = 0; i)< arguments.length; i++) { console.log(i + " параметр = " + arguments[i]); } } // вызовы функции myFunction myFunction(3, 7, 27, "JavaScript"); myFunction(); myFunction("Яблоки", "Груши", "Апельсины");

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

    // اعلان تابع var myCalc = function() ( // تکرار روی همه پارامترها با استفاده از حلقه for var i، sum = 0؛ برای (i = 0; i lt; arguments.length; i++) ( مجموع += آرگومان ها[i ] ; ) // برگرداندن مجموع به عنوان نتیجه بازگشت مجموع؛ ) // فراخوانی تابع (خروجی به کنسول) console.log(myCalc(4, 20, 17, -6));

    در نتیجه، شیء آرگومان ها را می توان در بدنه تابع پیاده سازی کرد:

    • بررسی تعداد آرگومان های ارسال شده؛
    • پردازش هر تعداد پارامتر

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

    تابع mainF(p1, p2) ( تابع childF() ( console.log("p1 = " + p1 + "; p2 = " + p2); ) childF(); ) mainF(3, 5); // p1 = 3; p2 = 5 mainF(4, 7); // p1 = 4; p2 = 7

    مقدار پیش فرض پارامتر

    شروع با ECMAScript 2015 (6) پارامتر تابعمی توانید مقداری را که به صورت پیش فرض خواهد داشت را تنظیم کنید.

    به عنوان مثال، اجازه دهید پارامتر "color" را روی مقدار پیش فرض آن "#009688" تنظیم کنیم:

    تابع setBGColor(color = "#009688") ( document.body.style.backgroundColor = color; ) setBGColor(); // رنگ پس زمینه #009688 setBGColor ("قرمز"); // رنگ پس زمینه قرمز خواهد بود

    قبل از ECMAScript 2015، می‌توانید یک پارامتر را به یک مقدار پیش‌فرض تنظیم کنید، به عنوان مثال، به این صورت بود:

    تابع setBGColor(color) ( color = color !== undefined ? color: "#009688"; // رنگ را به مقدار پیش فرض "#009688" document.body.style.backgroundColor = color; ) تنظیم کنید.

    پارامترهای باقی مانده

    اگر هنگام فراخوانی یک تابع، آرگومان های بیشتری نسبت به پارامترهای آن به آن ارسال کنید، می توانید با استفاده از به اصطلاح آرگومان های باقی مانده را دریافت کنید. پارامترهای باقیمانده (پاتامترهای بقیه). این ویژگی از ECMAScript 2015 در این زبان ظاهر شده است.

    // … mathAction) (مورد "جمع": نتیجه += مقدار؛ شکست؛ حالت "sumCube": نتیجه += مقدار**3؛ شکست؛ حالت "sumSquare": نتیجه += مقدار**2؛ شکست؛ پیش فرض: نتیجه = 0 ; ) ) ) نتیجه را برگرداند؛ ) console.log(doMath("sum", 3, 4, 21, -4)); // 24 (3 + 4 + 21 + (-4)) console.log(doMath("sumSquare", 1, 4)); // 17 (1^2 + 4^2) console.log(doMath("sumCube", 3, 2, 4)); // 99 (3^3 + 2^3 + 4^3)

    بیانیه بازگشت

    دستور return برای برگرداندن مقدار یا نتیجه ارزیابی عبارت تابع جاری در نظر گرفته شده است. مقدار یا عبارت باید با فاصله از بازگشت جدا شود. علاوه بر این، دستور return اجرای تابع را خاتمه می دهد، یعنی. تمام دستورالعمل های زیر اجرا نمی شود.

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

    // تابع تابع sayWelcome (userFirstName, userLastName) (اگر ((!userFirstName) || (!userLastName)) "Welcome, unonymous user" را برگرداند؛ در غیر این صورت "Welcome, " + userLastName + " " + userFirstName ; متغیر اعلام شخص var person; // نتیجه تابع sayWelcome را به متغیر person اختصاص دهید person = sayWelcome("Ivan","Ivanov"); // چاپ مقدار متغیر در کنسول console.log(person); //دستورالی که نتیجه تابع sayWelcome را به کنسول خروجی می دهد console.log(sayWelcome("Peter","Petrov")); //دستوری که نتیجه تابع sayWelcome را به کنسول خروجی می دهد console.log(sayWelcome("Sidorov")); جاوا اسکریپت - تابع با اعتبارسنجی پارامتر

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

    // 1. تابعی که هیچ تابع نتیجه ای را برنمی گرداند sayWelcome (userFirstName, userLastName) ( console.log("Welcome, " + userLastName + " " + userFirstName); ) // سعی کنید نتیجه را از تابعی دریافت کنید که این کار را انجام می دهد. چیزی را برنگردانید کنسول .log(sayWelcome ("ایوان"، "ایوانوف")); // 2. تابع حاوی دستور بازگشت بدون تابع مقدار sayDay (day) (day = "Today, " + day; return; //این دستور اجرا نخواهد شد زیرا بعد از عبارت return console.log(day) آمده است. ; ) // سعی کنید نتیجه تابعی را که حاوی عبارت بازگشتی است بدون مقدار console.log(sayDay("21 فوریه 2016")) بدست آورید. جاوا اسکریپت - از تابعی که چیزی برمی گرداند مقدار دریافت کنید

    اگر مقدار بازگشتی برای عبارت بازگشتی مشخص نشده باشد، همان نتیجه به دست خواهد آمد.

    بارگذاری بیش از حد تابع در جاوا اسکریپت

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

    زبان جاوا اسکریپت از بارگذاری بیش از حد تابع به روشی که برای مثال در زبان های C مانند اجرا می شود پشتیبانی نمی کند. آن ها در جاوا اسکریپت نمی توانید چندین تابع با نام یکسان ایجاد کنید که در یک محدوده هستند.

    عملکرد مشابهی را می توان در جاوا اسکریپت با استفاده از مراحل زیر پیاده سازی کرد:

    • برای بررسی اینکه آیا آرگومان ارسال شده است یا خیر، از یک شرط با بررسی مقدار آن برای undefined استفاده کنید.
    • برای بررسی تعداد آرگومان های ارسال شده به یک تابع، از ویژگی طول آرگومان شی استفاده کنید.
    • برای اطلاع از نوع مقدار آرگومان ارسال شده، از عملگر typeof یا instanceof استفاده کنید.
    • برای کار با تعداد متغیر آرگومان، از شیء arguments استفاده کنید.
    • با شروع با ECMAScript6، می توانید مقادیر پیش فرض را برای آرگومان ها مشخص کنید.

    به عنوان مثال، بیایید یک تابع ایجاد کنیم که بتوان آن را با یک یا دو آرگومان فراخوانی کرد:

    //اعلان تابعی که رنگ پس‌زمینه عناصر را تغییر می‌دهد تابع setBgColor(bgColor,elements) ( //اگر پارامتر عناصر هنگام فراخوانی مشخص نشده باشد if (elements=== تعریف نشده) (//سپس مقدار آن را روی "div" تنظیم کنید عناصر = "div "; ) // دریافت همه عناصر عناصر = $(عناصر)؛ // حلقه را از طریق تمام عناصر و تنظیم آنها به عناصر رنگ پس زمینه مشخص شده. every(function()($(this).css("background -color",bgColor) ; )))) /* تابع setBgColor را با یک پارامتر فراخوانی کنید. زیرا 2 پارامتر مشخص نشده است، سپس این تابع رنگ پس زمینه همه عناصر div را تغییر می دهد.*/ setBgColor("green"); /* تابع setBgColor را با 2 پارامتر فراخوانی کنید. زیرا 2 پارامتر تنظیم شده است، سپس این تابع فقط رنگ پس زمینه عناصر دکمه را تغییر می دهد.*/ setBgColor("#ff0000","button");

    بیایید تغییراتی در کد بالا ایجاد کنیم. یعنی مقدار پیش فرض پارامتر دوم را مشخص می کنیم:

    //اعلان تابعی که رنگ پس‌زمینه عناصر را تغییر می‌دهد //پارامتر عناصر توسط تابع پیش‌فرض روی "div" تنظیم می‌شود setBgColor(bgColor,elements = "div") (//get all element element = $(elements);/ /iterate همه عناصر را انتخاب کنید و رنگ پس‌زمینه مشخص شده را روی آن‌ها قرار دهید element.each(function()($(this).css("background-color",bgColor); )); ) //با تعیین یک پارامتر تابع setBgColor را فراخوانی کنید. setBgColor("سبز"); //با تعیین 2 پارامتر setBgColor تابع setBgColor را فراخوانی کنید("#ff0000","button");

    مثالی از نحوه اجرای یک تابع "overloaded" در جاوا اسکریپت که تعداد کالری مورد نیاز یک فرد در روز را محاسبه می کند:

    // تابع شرح تابع countCal(جنسیت، قد) ( // پارامترها: جنسیت (جنس) و قد (قد) نتیجه var؛ if ((جنس === 0) || (جنس === "مرد")) ( نتیجه = (قد - 100) * 20؛ ) در غیر این صورت ((جنس === 1) || (جنس === "زن")) (نتیجه = (قد - 105) * 19؛ ) اگر (نتیجه) ( // آرگومان‌ها - سطح فعالیت if (آگومان‌ها) (نتیجه *= آرگومان‌ها؛ ) console.log ("تعداد کالری برای زندگی عادی: " + نتیجه؛ ) else (consol.log("پارامترهای نامعتبر"); ) ) / * فراخوانی تابع و ارسال 2 آرگومان (1 - "man"، با نام جنسیت و آرگومان ها قابل دسترسی است؛ 2 - مقدار 185، با نام جنسیت و آرگومان ها قابل دسترسی است) */ countCal("man", 185)؛ /* فراخوانی تابع و ارسال 3 پارامتر به آن، اگرچه فقط 2 پارامتر در توضیحات تابع وجود دارد (در این حالت می توانید مقدار 3 پارامتر را فقط به عنوان آرگومان دریافت کنید) */ countCal(0, 185, 2);

    بازگشت

    بازگشت یک فراخوانی درون بدنه یک تابع به خودش است.

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

    تابع fact(n) ( if (n === 1) ( return 1; ) return fact(n-1) * n; ) console.log(fact(5)); // 120

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

    توابع داخلی (استاندارد) چیست؟

    جاوا اسکریپت دارای مجموعه عظیمی از توابع داخلی (استاندارد) است. این توابع قبلاً در خود موتور مرورگر توضیح داده شده است. تقریباً همه آنها روشهای یک یا آن شی هستند.

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

    // فراخوانی تابع alert alert("Some text"); جاوا اسکریپت - فراخوانی تابع هشدار

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

    فراخوانی تابع به صورت زیر انجام می شود:

    var a = functionName(par1, par2, …, parN);

    js توابع داخلی زیادی برای محاسبه عبارات ریاضی دارد. به عنوان مثال، تابع Math.sin سینوس زاویه را برمی گرداند (زاویه بر حسب رادیان داده می شود)، تابع Math.sqrt جذر عدد ارسال شده به آن را به عنوان پارامتر محاسبه می کند و غیره.

    برای مثال، جذر 256 را محاسبه می کنیم.

    var b = Math.sqrt(256);

    پس از اجرای کد یکی از دو مثال بالا، متغیر b حاوی مقدار 16 خواهد بود.

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

    عملکرد هشدار

    این تابع یک نمایش متنی از یک مقدار را به عنوان پارامتر می گیرد که در یک کادر خاکستری کسل کننده با دکمه OK نمایش داده می شود. تا زمانی که کاربر روی این دکمه کلیک نکند، اجرای اسکریپت ادامه نخواهد داشت.

    تابع document.write

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

    شیء ریاضی

    این شی شامل توابعی برای محاسبه عبارات ریاضی و برخی از ثابت ها می باشد. بعداً در مورد اشیا صحبت خواهیم کرد. برای استفاده از شیء Math، فقط باید به خاطر داشته باشید که برای دسترسی به خصوصیات آن (توابع و ثابت ها) باید Math.FunctionNameOrConstantName نوشته شود.

    ویژگی هایی که شی Math شامل می شود (کلمه "Math" حذف شده است):

    1. ثابت ها

    E 2.718281828459045
    LN10 2.302585092994046 (log natural 10)
    LN2 0.6931471805599453 (لگاریتم 2 طبیعی)
    LOG10E 0.4342944819032518 (لگاریتم اعشاری e)
    LOG2E 1.4426950408889634 (لگاریتم پایه 2 از e)
    PI 3.141592653589793
    SQRT1_2 0.7071067811865476 (ریشه مربع 0.5)
    SQRT2 1.4142135623730951 (ریشه دوم از دو)

    2. توابع مثلثاتی

    گناه - سینوس
    cos - کسینوس
    برنزه - مماس

    زاویه ای که این توابع به عنوان آرگومان می گیرند بر حسب رادیان است نه درجه. برای تبدیل یک زاویه از درجه به رادیان، آن را در Math.PI ضرب کنید و بر 180 تقسیم کنید. برعکس، برای تبدیل یک زاویه از رادیان به درجه، آن را در 180 ضرب کنید و بر Math.PI تقسیم کنید.

    بنابراین 60 درجه، π/3 رادیان، 30 درجه، π/6 رادیان، و 45 درجه، π/4 رادیان است.

    3. توابع مثلثاتی معکوس

    acos - کسینوس قوس عدد i.e. زاویه ای (به رادیان) که کسینوس آن برابر آرگومان است
    asin - arcsine عدد i.e. زاویه ای (به رادیان) که سینوس آن برابر برهان است
    آتان - مماس قوس عدد i.e. زاویه ای (به رادیان) که مماس آن برابر برهان است
    atan2 - مماس قوس ضریب دو آرگومان

    3. سایر ویژگی ها

    abs - مدول عدد
    طبقه - قسمت صحیح عدد، "طبقه" یا گرد کردن. توجه داشته باشید که برای مثال Math.floor(-0.9) و Math.floor(-0.1) -1 هستند نه صفر.
    سقف - گرد کردن یا "سقف"
    exp - مقدار عبارت e x را برمی‌گرداند که x آرگومان تابع است
    log - لگاریتم طبیعی یک عدد را برمی گرداند
    pow - دو آرگومان می گیرد و توانی را برمی گرداند که پایه آن آرگومان اول و توان آن آرگومان دوم است.
    max - تعداد دلخواه پارامتر را می پذیرد و حداکثر آنها را برمی گرداند
    min - تعداد دلخواه پارامتر را می پذیرد و حداقل آنها را برمی گرداند
    تصادفی - یک مقدار تصادفی از 0 تا 1 برمی گرداند
    گرد - یک عدد را به واحد گرد می کند
    sqrt - جذر یک عدد را محاسبه می کند

    ما بسیاری از توابع داخلی دیگر را در درس های زیر پوشش خواهیم داد، اما این همه برای امروز است.

    مه 24, 2011 در 01:13 ق.ظ

    پنج روش برای فراخوانی یک تابع

    • جاوا اسکریپت
    • ترجمه

    من اغلب با کد جاوا اسکریپت مواجه می شوم که در آن خطاها ناشی از سوء تفاهم از نحوه عملکرد توابع جاوا اسکریپت است (به هر حال، بیشتر این کد توسط من نوشته شده است). جاوا اسکریپت یک زبان چند پارادایم است و مکانیسم هایی برای برنامه نویسی تابعی دارد. وقت آن است که این احتمالات را کشف کنید. در این مقاله، پنج راه برای فراخوانی توابع در جاوا اسکریپت را به شما معرفی خواهم کرد.

    در مراحل اولیه یادگیری جاوا اسکریپت، مبتدیان معمولاً فکر می کنند که توابع موجود در آن تقریباً به همان شکلی است که مثلاً در C# کار می کند. اما مکانیسم های فراخوانی توابع در جاوا اسکریپت دارای تعدادی تفاوت مهم هستند و نادیده گرفتن آنها می تواند منجر به خطاهایی شود که یافتن آنها آسان نخواهد بود.

    بیایید یک تابع ساده بنویسیم که آرایه ای از سه عنصر را برمی گرداند - جریان این مقدار و دو آرگومان ارسال شده به تابع.
    تابع makeArray(arg1، arg2)( بازگشت [این، arg1، arg2]؛ )

    رایج ترین راه: تماس جهانی

    مبتدیان اغلب توابع را همانطور که در مثال بالا نشان داده شده است، اعلام می کنند. فراخوانی این تابع آسان است:
    makeArray("یک"، "دو"); // => [پنجره، "یک"، "دو" ]
    صبر کن. شی پنجره از کجا آمده است؟ چرا ما این برابر با پنجره داریم؟

    در جاوا اسکریپت، فرقی نمی کند که اسکریپت در مرورگر اجرا شود یا در محیط دیگری، همیشه تعریف شده است. شی جهانی. هر کدی در اسکریپت ما که به هیچ چیز "ضمیمه" نباشد (یعنی خارج از یک اعلان شی) در واقع در زمینه یک شی جهانی است. در مورد ما، makeArray فقط یک تابع در حال اجرا به تنهایی نیست. در واقع makeArray روشی از شی سراسری (در مورد اجرای کد در مرورگر) پنجره است. اثبات آن آسان است:
    alert(نوع window.methodThatDoesntExist); // => هشدار تعریف نشده (نوع window.makeArray); // => تابع
    یعنی فراخوانی makeArray("one", "two"); معادل فراخوانی window.makeArray("one", "two") است. .

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

    قانون فراخوانی تابع شماره 1:اگر تابع مستقیماً و بدون تعیین شیء فراخوانی شود (مثلاً myFunction())، مقدار آن شیء سراسری خواهد بود (پنجره در مورد اجرای کد در مرورگر).

    فراخوانی روش

    بیایید یک شی ساده بسازیم و makeArray را به روشی از آن تبدیل کنیم. ما شی را با استفاده از نماد واقعی اعلام می کنیم و سپس متد خود را فراخوانی می کنیم:
    // ایجاد یک شی var arrayMaker = ( someProperty: "some value", make: makeArray ); // فراخوانی متد make() arrayMaker.make("one", "two"); // => [ arrayMaker, "one", "two" ] // syntax جایگزین، از براکت مربع استفاده کنید arrayMaker["make"]("one", "two"); // => [ arrayMaker، "one"، "two"]
    تفاوت را ببین؟ ارزش این در این مورد خود شی است. چرا مانند مورد قبلی پنجره نمی شود، زیرا اعلان تابع تغییر نکرده است؟ کل راز این است که چگونه توابع در جاوا اسکریپت منتقل می شوند. Function یک نوع استاندارد جاوا اسکریپت است که در واقع یک شی است و مانند هر شی دیگری، توابع را می توان ارسال و کپی کرد. در این مورد، ما به نوعی کل تابع، از جمله لیست آرگومان و بدنه را کپی کردیم و شی حاصل را به ویژگی make شیء arrayMaker اختصاص دادیم. این معادل این اعلامیه است:
    var arrayMaker = ( someProperty: "Some value"; make: function (arg1, arg2) ( return [ this, arg1, arg2]; ) );
    قانون شماره 2 فراخوانی تابع:در تابعی که با استفاده از سینتکس فراخوانی متد نامیده می شود، مانند ()obj.myFunction یا obj["myFunction"]() ، این obj خواهد بود.

    عدم درک این اصل ساده و به طور کلی اغلب منجر به خطاهایی در مدیریت رویداد می شود:

    با کلیک بر روی دکمه اول پیام نمایش داده می شود btn1، زیرا در این حالت تابع را به عنوان متد فراخوانی می کنیم و این در داخل تابع مقدار شیئی را که این متد به آن تعلق دارد بدست می آورد. با کلیک بر روی دکمه دوم نمایش داده می شود پنجره، زیرا در این مورد ما به طور مستقیم buttonClicked را فراخوانی می کنیم (یعنی نه مانند obj.buttonClicked()). همین اتفاق می افتد زمانی که یک کنترل کننده رویداد را روی تگ عنصر اختصاص می دهیم، مانند مورد دکمه سوم. با کلیک بر روی دکمه سوم، همان پیغام مورد نظر برای دکمه دوم نمایش داده می شود.

    هنگام استفاده از کتابخانه هایی مانند jQuery، لازم نیست به آن فکر کنید. جی کوئری از بازنویسی این مقدار در کنترل کننده رویداد مراقبت می کند تا این مقدار عنصری باشد که رویداد را اجرا می کند:
    // از jQuery استفاده کنید $("#btn1").click(function() ( alert(this.id); // jQuery مطمئن خواهد شد که "this" یک دکمه است ));
    جی کوئری چگونه مقدار این را تغییر می دهد؟ در زیر می خوانید.

    دو روش دیگر: application() و call()

    به طور منطقی، هر چه بیشتر از توابع استفاده کنید، بیشتر اوقات باید آنها را منتقل کنید و آنها را در زمینه های مختلف فراخوانی کنید. اغلب نیاز به نادیده گرفتن ارزش این وجود دارد. اگر به خاطر داشته باشید، توابع در جاوا اسکریپت یک شی هستند. در عمل، این بدان معنی است که توابع دارای روش های از پیش تعریف شده هستند. application() و call() دو مورد از آنها هستند. آنها به شما اجازه می دهند که این مقدار را نادیده بگیرید:
    var car = ( سال: 2008، مدل: "Dodge Bailout" ); makeArray.apply(car, [ "one", "two" ]); // => [ car, "one", "two" ] makeArray.call(car, "one", "two"); // => [ ماشین، "یک"، "دو" ]
    این دو روش بسیار شبیه هم هستند. پارامتر اول این را نادیده می گیرد. تفاوت بین این دو در آرگومان های بعدی است: Function.apply() آرایه ای از مقادیر را برای ارسال به تابع می گیرد، در حالی که Function.call() آرگومان ها را جداگانه می گیرد. در عمل، به نظر من، استفاده از application() راحت تر است.

    قانون شماره 3 فراخوانی تابع:اگر می‌خواهید مقدار این را بدون کپی کردن تابع در یک شی دیگر لغو کنید، می‌توانید از myFunction.apply(obj) یا myFunction.call(obj) استفاده کنید.

    سازندگان

    من به جزئیات در مورد اعلام انواع سفارشی در جاوا اسکریپت نمی پردازم، اما لازم می دانم به شما یادآوری کنم که هیچ کلاسی در جاوا اسکریپت وجود ندارد و هر نوع سفارشی نیاز به سازنده دارد. همچنین، روش‌های نوع سفارشی بهتر است از طریق نمونه اولیه، که یکی از ویژگی‌های تابع سازنده است، اعلام شوند. بیایید نوع خود را ایجاد کنیم:
    // اعلان تابع سازنده ArrayMaker(arg1, arg2) ( this.someProperty = "مهم نیست"؛ این. theArray = [ this, arg1, arg2 ]; ) // اعلان متدها ArrayMaker.prototype = ( someMethod: تابع () ( alert( "Called someMethod"); ), getArray: function () ( return this.theArray; ) ); var am = new ArrayMaker("one", "two"); var other = new ArrayMaker("اول"، "دوم"); am.getArray(); // => [ am، "یک"، "دو" ]
    نکته مهم در این مثال وجود اپراتور جدید قبل از فراخوانی تابع است. اگر نبود، یک فراخوانی سراسری خواهد بود و خصوصیات ایجاد شده در سازنده به شی سراسری اشاره می کنند. ما به این نیاز نداریم همچنین، سازنده ها معمولاً مقادیر را به صراحت برمی گردانند. بدون عملگر جدید، سازنده بدون تعریف باز می گردد، با آن این را برمی گرداند. نامگذاری سازندگان با حروف بزرگ سبک خوبی است. این نیاز به اپراتور جدید را به شما یادآوری می کند.

    در غیر این صورت، کد داخل سازنده به احتمال زیاد شبیه کدی خواهد بود که شما به زبان دیگری می‌نویسید. ارزش این در این مورد شی جدیدی است که شما ایجاد می کنید.

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

    نتیجه

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

    مردم فکر می کنند که علم کامپیوتر یک هنر برای نوابغ است. در واقعیت، برعکس است - فقط بسیاری از مردم کارهایی را انجام می دهند که روی هم قرار می گیرند، گویی دیواری از سنگریزه های کوچک درست می کنند.

    دونالد کنوت

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

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

    یک فرد بالغ روسی زبان به طور متوسط ​​حدود 10000 کلمه می داند. یک زبان برنامه نویسی کمیاب شامل 10000 دستور داخلی است. و واژگان یک زبان برنامه نویسی با وضوح بیشتری تعریف شده است، بنابراین انعطاف پذیری کمتری نسبت به زبان انسانی دارد. بنابراین، معمولاً برای جلوگیری از تکرار بی مورد، باید کلمات خود را به آن اضافه کنیم.

    تعریف تابع

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

    var Square = تابع (x) ( بازگشت x * x; ); console.log(square(12)); // → 144

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

    یک تابع ممکن است چندین پارامتر یا اصلاً نداشته باشد. در مثال زیر، makeNoise لیستی از پارامترها ندارد، در حالی که power دارای دو پارامتر است:

    Var makeNoise = function() ( console.log("Fuck!"); ); makeNoise(); // → مزخرف! قدرت var = تابع (پایه، توان) (نتیجه var = 1؛ برای (تعداد var = 0؛ تعداد< exponent; count++) result *= base; return result; }; console.log(power(2, 10)); // → 1024

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

    پارامترها و دامنه

    پارامترهای تابع دقیقاً مانند متغیرها هستند، اما مقادیر اولیه آنها هنگام فراخوانی تابع تنظیم می شود و نه در کد آن.

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

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

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

    var x = "خارج"; var f1 = function() ( var x = "inside f1"; ); f1(); ورود به سیستم کنسول (x); // → var f2 = function() ( x = "inside f2"; ); f2(); ورود به سیستم کنسول (x); // → داخل f2

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

    دامنه های تو در تو

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

    به عنوان مثال، تابع نسبتاً بی‌معنی زیر حاوی دو تابع دیگر است:

    var landscape = function() (var result = ""; var flat = function(size) ( for (var count = 0; count< size; count++) result += "_"; }; var mountain = function(size) { result += "/"; for (var count = 0; count < size; count++) result += """; result += "\\"; }; flat(3); mountain(4); flat(6); mountain(1); flat(1); return result; }; console.log(landscape()); // → ___/""""\______/"\_

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

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

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

    var چیزی = 1; ( var something = 2; // کاری را با متغیر چیزی انجام دهید... ) // خروج از بلوک...

    اما چیزی در داخل بلوک همان متغیر خارجی است. اگرچه چنین بلوک هایی مجاز هستند، اما استفاده از آنها فقط برای دستورات if و حلقه ها منطقی است.

    اگر این برای شما عجیب به نظر می رسد، نه تنها برای شما چنین است. جاوا اسکریپت 1.7 کلمه کلیدی let را معرفی کرد که مانند var کار می کند، اما متغیرهایی را ایجاد می کند که محلی برای هر بلوک مشخص هستند، نه فقط تابع.

    به عنوان ارزش عمل می کند

    نام توابع معمولاً به عنوان نام یک قطعه از یک برنامه استفاده می شود. چنین متغیری یک بار تنظیم می شود و تغییر نمی کند. بنابراین به راحتی می توان یک تابع را با نام آن اشتباه گرفت.

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

    Var launchMissiles = تابع (مقدار) ( ‎missileSystem. launch("لطفا!"); if (safeMode) launchMissiles = function(value) (/* release */);

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

    اعلام عملکرد

    یک نسخه کوتاه تر از عبارت "var Square = تابع ..." وجود دارد. کلمه کلیدی تابع را می توان در ابتدای یک عبارت استفاده کرد:

    تابع مربع (x) (برگردان x * x؛ )

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

    Console.log("آینده می گوید:"، future()); تابع future() ( بازگشت "ما هنوز هیچ ماشین پرنده ای نداریم."؛)

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

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

    مثال تابع () ( تابع a() () // هنجار اگر (چیزی) ( تابع b() () // Ay-yy-yy! ) )

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

    تابع greet(who) ( console.log("Hi, " + who); ) greet("Semyon"); console.log ("Pokeda");

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

    به صورت شماتیک، این را می توان به صورت زیر نشان داد:

    Top greet console.log سلام top console.log بالا

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

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

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

    تابع chicken() ( return egg(); ) function egg() ( return chicken(); ) console.log(chicken() + " first first."); // → ??

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

    هشدار ("سلام"، "عصر بخیر"، "سلام به همه!");

    به طور رسمی، تابع یک آرگومان می گیرد. با این حال، هنگامی که این گونه به چالش کشیده می شود، او شکایت نمی کند. بقیه استدلال ها را نادیده می گیرد و «سلام» را نشان می دهد.

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

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

    نکته مثبت این است که می توانید توابعی ایجاد کنید که آرگومان های اختیاری را دریافت کنند. به عنوان مثال، در نسخه بعدی تابع توان، می توان آن را با دو و یک آرگومان فراخوانی کرد - در حالت دوم، توان برابر با دو خواهد بود و تابع مانند یک مربع عمل می کند.

    توان تابع (پایه، توان) (اگر (شار == ​​تعریف نشده) توان = 2؛ نتیجه var = 1؛ برای (تعداد var = 0؛ تعداد< exponent; count++) result *= base; return result; } console.log(power(4)); // → 16 console.log(power(4, 3)); // → 64

    در فصل بعدی، خواهیم دید که چگونه بدنه یک تابع می تواند تعداد دقیق آرگومان های ارسال شده به آن را به شما بگوید. این مفید است زیرا به شما اجازه می دهد تا یک تابع ایجاد کنید که هر تعداد آرگومان را بگیرد. به عنوان مثال، console.log از این ویژگی استفاده می کند و تمام آرگومان های ارسال شده به آن را چاپ می کند:

    Console.log("R"، 2، "D"، 2); // → R 2 D 2

    بسته شدن

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

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

    تابع wrapValue(n) ( var localVariable = n; return function() ( return localVariable; ) var wrap1 = wrapValue(1); var wrap2 = wrapValue(2); ورود به سیستم کنسول (wrap1()); // → 1 console.log(wrap2()); // → 2

    این معتبر است و همانطور که باید کار می کند - دسترسی به متغیر باقی می ماند. علاوه بر این، چندین نمونه از یک متغیر می‌توانند در یک زمان وجود داشته باشند، و این واقعیت را تأیید می‌کند که متغیرهای محلی با هر فراخوانی تابع دوباره ایجاد می‌شوند.

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

    با کمی تغییر، مثال خود را به تابعی تبدیل می کنیم که اعداد را در هر عدد داده شده ضرب می کند.

    ضریب تابع (ضریب) ( تابع بازگشتی (عدد) (عدد بازگشتی * ضریب؛ ) var double = ضرب (2); console.log(twice(5)); // → 10

    یک متغیر جداگانه مانند localVariable از مثال wrapValue دیگر مورد نیاز نیست. از آنجایی که پارامتر خود یک متغیر محلی است.

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

    در مثال ما، ضریب یک قطعه کد منجمد شده را که در متغیر double ذخیره می کنیم، برمی گرداند. آخرین خط تابع موجود در متغیر را فراخوانی می کند که کد ذخیره شده را فعال می کند (شماره بازگشت * فاکتور؛). همچنان به متغیر فاکتوری که هنگام فراخوانی ضریب تعریف شده است دسترسی دارد و همچنین به آرگومان ارسال شده در زمان unfreeze (5) به عنوان پارامتر عددی دسترسی دارد.

    بازگشت

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

    تابع قدرت(پایه، توان) (اگر (نما == 0) برگرداند 1؛ در غیر این صورت، پایه * توان (پایه، توان - 1) را برگرداند؛ ) console.log(power(2، 3)); // → 8

    ریاضیدانان قدرت را اینگونه تعریف می کنند و شاید این مفهوم را زیباتر از یک چرخه توصیف می کند. این تابع بارها خود را با آرگومان های مختلف فراخوانی می کند تا به ضرب چندگانه برسد.

    با این حال، این پیاده سازی یک مشکل دارد - در یک محیط معمولی جاوا اسکریپت، 10 برابر کندتر از نسخه دارای حلقه است. حلقه زدن ارزان تر از فراخوانی یک تابع است.

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

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

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

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

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

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

    در اینجا یک معما برای شما وجود دارد: می توانید تعداد نامتناهی اعداد را بدست آورید که با عدد 1 شروع می شوند و سپس 5 را با هم جمع می کنند یا در 3 ضرب می کنند. جمع و ضرب هایی که به عدد معینی منتهی می شود؟ برای مثال می توان عدد 13 را با ضرب 1 در 3 و سپس دوبار جمع کردن 5 بدست آورد. و عدد 15 به طور کلی غیرممکن است که به آن دست پیدا کنید.

    راه حل بازگشتی:

    تابع findSolution(target) ( تابع find(شروع، تاریخچه) (اگر (شروع == هدف) تاریخچه را برمی گرداند؛ در غیر این صورت اگر (شروع > هدف) را برگرداند null؛ در غیر این صورت بازگشت find(start + 5، "(" + history + " + 5)") || find(start * 3, "(" + history + " * 3)"); ) return find(1, "1"); ) console.log(findSolution(24)); // → (((1 * 3) + 5) * 3)

    این مثال لزوما کوتاه ترین راه حل را پیدا نمی کند - هر کدام را برآورده می کند. من انتظار ندارم که شما فوراً نحوه عملکرد برنامه را درک کنید. اما بیایید به انتهای این تمرین عالی در تفکر بازگشتی بپردازیم.

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

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

    برای درک بهتر اینکه تابع چگونه به اثر مورد نظر دست می یابد، اجازه دهید به فراخوانی های آن که در جستجوی راه حلی برای عدد 13 رخ می دهد نگاه کنیم.

    Find(1, "1") find(6, "(1 + 5)") find(11, "((1 + 5) + 5)") find(16, "((1 + 5) + 5 (( 3، "(1 * 3)") find(8، "((1 * 3) + 5)") find(13، "(((1 * 3) + 5) + 5)") یافت شد!

    تورفتگی عمق پشته تماس را نشان می دهد. اولین باری که تابع Find دوبار خود را فراخوانی می کند تا راه حل هایی را که با (1 + 5) و (1 * 3) شروع می شوند بررسی کند. اولین فراخوانی به دنبال راه حلی می گردد که با (1 + 5) شروع می شود و از بازگشت برای بررسی همه راه حل هایی که عددی کمتر یا مساوی با عدد مورد نظر به دست می دهند، استفاده می کند. آن را پیدا نمی کند و null برمی گرداند. سپس اپراتور || و به فراخوانی تابعی می‌پرد که گزینه (1 * 3) را بررسی می‌کند. در اینجا ما خوش شانس هستیم، زیرا در سومین فراخوانی بازگشتی 13 دریافت می کنیم. این فراخوانی یک رشته را برمی گرداند و هر یک از || این رشته را در طول مسیر از بالا عبور می دهد و در نتیجه راه حل را برمی گرداند.

    توابع رشد

    دو روش کم و بیش طبیعی برای معرفی توابع به یک برنامه وجود دارد.

    ابتدا کدهای مشابه را چندین بار می نویسید. از این کار باید اجتناب شود - کد بیشتر به معنای فضای بیشتر برای خطاها و مطالب خواندن بیشتر برای کسانی است که سعی در درک برنامه دارند. بنابراین ما عملکرد تکرارشونده را می گیریم، نام خوبی برای آن می گذاریم و آن را در یک تابع قرار می دهیم.

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

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

    007 گاو 011 مرغ

    بدیهی است که ما به یک تابع با دو آرگومان نیاز داریم. بیایید کد نویسی را شروع کنیم.
    // printFarmInventory تابع printFarmInventory(گاو، مرغ) ( var cowString = String(cows)؛ while (cowString.length< 3) cowString = "0" + cowString; console.log(cowString + " Коров"); var chickenString = String(chickens); while (chickenString.length < 3) chickenString = "0" + chickenString; console.log(chickenString + " Куриц"); } printFarmInventory(7, 11);

    اگر .length را به یک رشته اضافه کنیم، طول آن را بدست می آوریم. معلوم می شود که حلقه های while صفرهای ابتدایی را به اعداد اضافه می کنند تا زمانی که رشته ای از 3 کاراکتر به دست آورند.

    آماده! اما به محض ارسال کد برای کشاورز (البته به همراه یک چک سنگین)، او زنگ می‌زند و به ما می‌گوید که در مزرعه خوک دارد و آیا می‌توانیم خروجی تعداد خوک‌ها را اضافه کنیم. به برنامه؟

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

    // outputZeroPaddedWithLabel تابع printZeroPaddedWithLabel(number, label) ( var numberString = String(number)؛ while (numberString.length< 3) numberString = "0" + numberString; console.log(numberString + " " + label); } // вывестиИнвентаризациюФермы function printFarmInventory(cows, chickens, pigs) { printZeroPaddedWithLabel(cows, "Коров"); printZeroPaddedWithLabel(chickens, "Куриц"); printZeroPaddedWithLabel(pigs, "Свиней"); } printFarmInventory(7, 11, 3);

    آثار! اما نام printZeroPaddedWithLabel کمی عجیب است. این سه چیز - خروجی، لایه صفر و یک برچسب - را در یک تابع ترکیب می کند. به جای پر کردن کل قطعه تکراری در یک تابع، بیایید یک مفهوم را برجسته کنیم:

    // اضافه کردن تابع Zeros zeroPad(عدد، عرض) ( var string = string(number)؛ while (string.length< width) string = "0" + string; return string; } // вывестиИнвентаризациюФермы function printFarmInventory(cows, chickens, pigs) { console.log(zeroPad(cows, 3) + " Коров"); console.log(zeroPad(chickens, 3) + " Куриц"); console.log(zeroPad(pigs, 3) + " Свиней"); } printFarmInventory(7, 16, 3);

    تابعی با نام زیبا و توصیفی zeroPad درک کد را آسان‌تر می‌کند. و می تواند در بسیاری از موقعیت ها استفاده شود، نه تنها در مورد ما. به عنوان مثال، برای نمایش جداول فرمت شده با اعداد.

    عملکردها چقدر باید هوشمند و همه کاره باشند؟ می‌توانیم یک تابع ساده بنویسیم که یک عدد را با صفر تا سه موقعیت قرار می‌دهد، و همچنین یک تابع همه‌منظوره فانتزی برای قالب‌بندی اعداد که از کسر، اعداد منفی، تراز نقطه‌ها، پر کردن کاراکترهای مختلف و غیره پشتیبانی می‌کند.

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

    توابع و عوارض جانبی

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

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

    یک تابع خالص نوع خاصی از تابع برگردان ارزش است که نه تنها عوارض جانبی ندارد، بلکه به عوارض جانبی بقیه کد نیز بستگی ندارد - به عنوان مثال، با متغیرهای سراسری که به طور تصادفی قابل تغییر هستند کار نمی کند. یک جای دیگر. یک تابع خالص، هنگامی که با همان آرگومان ها فراخوانی می شود، همان نتیجه را برمی گرداند (و هیچ کار دیگری انجام نمی دهد) - که بسیار خوب است. کار کردن با او آسان است. فراخوانی چنین تابعی را می توان به صورت ذهنی با نتیجه کار آن جایگزین کرد، بدون اینکه معنای کد تغییر کند. وقتی می‌خواهید چنین تابعی را تست کنید، می‌توانید به سادگی آن را فراخوانی کنید و مطمئن باشید که اگر در این زمینه کار کند، در هر یک از آنها کار خواهد کرد. عملکردهای نه چندان خالص بسته به عوامل بسیاری می توانند نتایج متفاوتی را برگردانند و دارای عوارض جانبی هستند که آزمایش و محاسبه آنها دشوار است.

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

    نتیجه

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

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

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

    تمرینات

    کمترین
    در فصل قبل تابع Math.min ذکر شد که کوچکترین آرگومان های خود را برمی گرداند. حالا ما می توانیم چنین تابعی را خودمان بنویسیم. یک تابع min بنویسید که دو آرگومان را بگیرد و حداقل آنها را برگرداند.

    Console.log(min(0, 10)); // → 0 console.log(min(0, -10)); // → -10

    بازگشت
    دیدیم که عملگر % (باقیمانده) می تواند برای تعیین زوج بودن یک عدد (% 2) استفاده شود. در اینجا روش دیگری برای تعیین وجود دارد:

    صفر زوج است.
    واحد فرد است.
    هر عدد N برابر با N-2 است.

    مطابق این قوانین یک تابع isEven بازگشتی بنویسید. باید یک عدد بگیرد و یک مقدار بولی برگرداند.

    آن را روی 50 و 75 تست کنید. سعی کنید به آن -1 بدهید. چرا او این گونه رفتار می کند؟ میشه یه جوری درستش کرد؟

    آن را روی 50 و 75 تست کنید. ببینید در -1 چگونه رفتار می کند. چرا؟ آیا می توانید راهی برای رفع این مشکل فکر کنید؟

    Console.log(isEven(50)); // → true console.log(isEven(75)); // → false console.log(isEven(-1)); // → ??

    لوبیا را می شماریم.

    کاراکتر شماره N یک رشته را می توان با اضافه کردن .charAt(N)("string".charAt(5)) به آن، به روشی مشابه به دست آوردن طول یک رشته با طول . بدست آورد. مقدار بازگشتی یک رشته کاراکتری خواهد بود (به عنوان مثال، "k"). اولین کاراکتر رشته دارای موقعیت 0 است، به این معنی که آخرین کاراکتر دارای string.length - 1 موقعیت است. به عبارت دیگر، یک رشته دو کاراکتری دارای طول 2 است و موقعیت کاراکترهای آن 0 و 1 خواهد بود.

    یک تابع countBs بنویسید که یک رشته را به عنوان آرگومان می گیرد و تعداد کاراکترهای "B" در رشته را برمی گرداند.

    سپس یک تابع countChar بنویسید که کمی مانند countBها کار می کند، به جز اینکه پارامتر دوم را می گیرد، کاراکتری که در رشته به دنبال آن می گردیم (به جای اینکه فقط تعداد کاراکترهای "B" را بشماریم). برای انجام این کار، تابع countBs را بازنویسی کنید.