نحوه راه اندازی گوشی های هوشمند و رایانه های شخصی پرتال اطلاعاتی

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

کارکرد

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

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

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

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

تعریف توابع

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

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

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

یک جفت پرانتز در اطراف فهرستی از شناسه‌های صفر یا بیشتر، که با کاما از هم جدا شده‌اند.

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

یک جفت بریس فرفری با دستورات جاوا اسکریپت صفر یا بیشتر در داخل

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

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

// نام و مقادیر تمام ویژگی های تابع شیء obj را چاپ می کند printprops (obj) (برای (var p در obj) console.log (p + ":" + obj [p] + "\ n"); ( dx * dx + dy * dy ؛) // تابع بازگشتی (خود را فراخوانی می کند) که تابع فاکتوریل را فاکتوریل (x) محاسبه می کند (اگر (x)

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

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

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

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

توابع فراخوانی

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

اگر عبارت فراخوانی تابع یک عبارت فراخوانی ویژگی باشد - اگر تابع خاصیت یک شی یا عنصری از یک آرایه (یعنی یک متد) باشد - آنگاه عبارت فراخوانی عبارت فراخوانی متد است. قطعه زیر چندین نمونه از عبارات فراخوانی تابع معمولی را نشان می دهد:

لوازم چاپ ((x: 4، سن: 24)); var d = فاصله (1،1،5،6)؛ var f = فاکتوریل (5) / فاکتوریل (12); f = مربع (5)؛

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

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

روشچیزی نیست جز تابعی که به عنوان ویژگی یک شی ذخیره می شود. اگر یک تابع func و یک شی obj دارید، می توانید یک متد بر روی شی obj با نام متد تعریف کنید، همانطور که در زیر نشان داده شده است:

// تعریف یک شی و تابع ساده var obj = (); تابع func (a, b) (a + b;) // اضافه کردن متد obj به obj object.method = func; // اکنون می توانید این متد را فراخوانی کنید var result = obj.method (4, 5);

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

نتیجه = obj.method (4، 5); result = obj ["روش"] (4، 5);

آرگومان ها و مقدار بازگشتی فراخوانی متد به همان روشی که یک فراخوانی تابع معمولی مدیریت می شود. با این حال، فراخوانی روش یک تفاوت مهم دارد: زمینه فراخوانی. عبارت دسترسی به ویژگی از دو بخش تشکیل شده است: یک شی (در این مورد obj) و یک نام ویژگی (روش). در چنین عبارات فراخوانی روش، شی obj به متن فراخوانی تبدیل می شود و بدنه تابع می تواند با استفاده از کلمه کلیدی this به این شی اشاره کند. برای مثال:

Var obj = (x: 0، y: 0، // روش جمع: تابع (a, b) (this.x = a; this.y = b;)، // مجموع روش دیگر: تابع () (این را برگردانید .x + this.y)); // روش های فراخوانی obj.add (15, 4); console.log (obj.sum ()); // نوزده

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

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

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

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

استدلال های اختیاری

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

// نام های برشماری شده // ویژگی های شی obj را به آرایه arr اضافه کنید و آن را برگردانید. اگر آرگومان // arr ارسال نشد، یک تابع آرایه جدید getPropertyNames (obj, / * اختیاری * / arr) ایجاد و برگردانید (اگر (arr === تعریف نشده) arr =; // اگر آرایه تعریف نشده است، ایجاد کنید یک تابع جدید برای ( خاصیت var در obj) arr.push (ویژگی)؛ return arr;) // این تابع را می توان با 1 یا 2 آرگومان فراخوانی کرد: var a = getPropertyNames ((x: 1, y: 1)); // دریافت خواص شی در یک آرایه جدید getPropertyNames ((z: 5), a); // ویژگی های شی جدید را به این آرایه اضافه کنید console.log (a); // ["x"، "y"، "z"]

توجه داشته باشید که هنگام اعلان توابع، آرگومان های اختیاری باید به لیست آرگومان پایان دهند تا حذف شود. برنامه نویسی که یک فراخوانی برای تابع شما می نویسد، نمی تواند آرگومان دوم را پاس کند و در عین حال آرگومان اول را حذف کند: او مجبور خواهد شد که در آرگومان اول به صراحت تعریف نشده ارسال کند. همچنین به کامنت / * اختیاری * / در تعریف تابع توجه کنید که بر اختیاری بودن پارامتر تأکید دارد.

لیست های آرگومان با طول متغیر

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

فرض کنید تابع تعریف شده است که به یک آرگومان x نیاز دارد. اگر این تابع را با دو آرگومان فراخوانی کنید، اولین آرگومان در داخل تابع با نام پارامتر x یا به عنوان آرگومان در دسترس خواهد بود. آرگومان دوم فقط به عنوان آرگومان در دسترس خواهد بود. علاوه بر این، آرگومان‌ها مانند آرایه‌های واقعی دارای ویژگی length هستند که تعداد عناصر مورد نیاز را تعیین می‌کند. یعنی در بدنه تابعی که با دو آرگومان فراخوانی می شود، arguments.length 2 است.

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

تابع تابع (x, y, z) (// ابتدا بررسی می‌کند که آیا تعداد صحیح آرگومان‌ها ارسال شده است یا نه (arguments.length! = 3) (خطای جدید ("Function Func was call with" + arguments.length + "آگومان ها، اما 3.")) // و اکنون خود کد تابع ...)

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

شیء Arguments یک ویژگی مهم توابع جاوا اسکریپت را نشان می دهد: آنها می توانند برای گرفتن هر تعداد آرگومان نوشته شوند. تابع زیر هر تعداد آرگومان را می گیرد و مقدار بزرگترین آنها را برمی گرداند (عملکرد داخلی Math.max () مشابه رفتار می کند):

تابع maxNumber () (var m = Number.NEGATIVE_INFINITY؛ // همه آرگومان ها را حلقه بزنید، بزرگترین آنها را برای (var i = 0; im) m = آرگومان ها [i]، // بزرگترین بازده را پیدا کنید و // ذخیره کنید. m ;) var بزرگترین = حداکثر تعداد (1، 10، 100، 2، 3، 1000، 4، 5، 10000، 6)؛ // 10000

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

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

به خاطر داشته باشید که آرگومان ها در واقع یک آرایه نیستند - آنها یک شی Arguments هستند. هر شی Arguments دارای عناصر آرایه شماره گذاری شده و ویژگی length است، اما از نظر فنی یک آرایه نیست. بهتر است آن را به عنوان یک شی با برخی ویژگی های شماره گذاری شده در نظر بگیرید.

شی Arguments علاوه بر عناصر آرایه خود، ویژگی ها را تعریف می کند تماس گیرندهو تماس گیرنده... تلاش برای تغییر مقادیر این ویژگی ها در حالت سخت ECMAScript 5 تضمینی برای ایجاد یک استثنا TypeError است. با این حال، در حالت سست، استاندارد ECMAScript بیان می‌کند که ویژگی callee به تابع در حال اجرا اشاره دارد. ویژگی فراخوان استاندارد نیست، اما در بسیاری از پیاده سازی ها وجود دارد و به تابعی اشاره دارد که فعلی را فراخوانی کرده است.

ویژگی caller را می توان برای دسترسی به پشته تماس استفاده کرد و ویژگی callee به ویژه برای فراخوانی بازگشتی توابع بدون نام مفید است:

فاکتوریل وار = تابع (x) (اگر (x

خواص و روش توابع

دیدیم که توابع را می توان به عنوان مقادیر در برنامه های جاوا اسکریپت استفاده کرد. عملگر typeof رشته "function" را برای توابع برمی گرداند، اما توابع در جاوا اسکریپت در واقع نوع خاصی از شی هستند. و از آنجایی که توابع اشیا هستند، مانند هر شیء دیگری دارای خواص و متدهایی هستند. حتی یک سازنده Function () وجود دارد که اشیاء تابع جدید را ایجاد می کند. بخش‌های فرعی زیر ویژگی‌ها و روش‌های توابع را توضیح می‌دهند.

دارایی طول

در بدنه تابع، ویژگی arguments.length تعداد آرگومان های ارسال شده به تابع را تعیین می کند. با این حال، ویژگی length خود تابع معنای متفاوتی دارد. این ویژگی فقط خواندنی تعداد آرگومان هایی را که تابع انتظار دارد دریافت کند - تعداد پارامترهای اعلام شده را برمی گرداند.

قطعه زیر تابعی به نام check () را تعریف می کند که آرایه ای از آرگومان ها را از یک تابع دیگر دریافت می کند. ویژگی arguments.length (تعداد آرگومان‌هایی که در واقع ارسال شده است) را با ویژگی arguments.callee.length (تعداد آرگومان‌های مورد انتظار) مقایسه می‌کند تا مشخص کند آیا تابع به اندازه‌ای که انتظار دارد آرگومان ارسال شده است یا خیر. اگر مقادیر مطابقت نداشته باشند، یک استثنا ایجاد می شود. تابع check () توسط تابع تست تابع () دنبال می شود که نحوه استفاده از تابع check () را نشان می دهد:

// این تابع از arguments.callee استفاده می‌کند، بنابراین // در بررسی عملکرد حالت سخت (args) کار نمی‌کند (var actual = args.length; // تعداد واقعی آرگومان‌ها var expect = args.callee.length؛ // آرگومان های عدد مورد انتظار اگر (واقعی! == انتظار می رود) // اگر مطابقت ندارند، خطای جدید ("منتظره:" + انتظار می رود + "؛ دریافت شده" + واقعی؛) تابع تابع (x، y، z) (/ / تعداد آرگومان‌های مورد انتظار و بررسی واقعی (آگومان‌ها) را بررسی کنید؛ // اکنون بقیه تابع بازگشت x + y + z;) را اجرا کنید.

ویژگی نمونه اولیه

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

نمونه اولیه و ویژگی نمونه اولیه در مقاله قبلی مورد بحث قرار گرفت.

متدهای () را فراخوانی و () اعمال کنید

متدهای فراخوانی () و اعمال () به شما این امکان را می دهد که به طور غیرمستقیم یک تابع را فراخوانی کنید، گویی متد یک شیء دیگر است. اولین آرگومان برای فراخوانی () و اعمال () شیئی است که تابع بر روی آن فراخوانی می شود. این آرگومان زمینه فراخوانی را تعریف می کند و به مقدار کلمه کلیدی this در بدنه تابع تبدیل می شود. برای فراخوانی func () (بدون آرگومان) به عنوان متد obj، می توانید از یکی از متدهای فراخوانی () یا اعمال () استفاده کنید:

Func.call (obj); func.apply (obj);

هر یک از این متدهای فراخوانی معادل قطعه زیر است (با فرض اینکه obj خاصیتی به نام m ندارد):

Obj.m = func; // به طور موقت تابع را به روش obj بسازید obj.m (); // آن را بدون آرگومان فراخوانی کنید. حذف obj.m; // روش موقت را حذف کنید.

در حالت سخت ECMAScript 5، اولین آرگومان متدهای فراخوانی () و اعمال () به این مقدار تبدیل می شود، حتی اگر یک مقدار ساده، تهی یا تعریف نشده باشد. در ECMAScript 3 و حالت غیر دقیق، مقادیر تهی و تعریف نشده با شی سراسری جایگزین می شوند و مقدار ساده با شی wrapper مربوطه جایگزین می شود.

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

مثال زیر استفاده عملی از متد فراخوانی () را نشان می دهد:

// در زیر دو تابع وجود دارد که خواص و // مقادیر ویژگی یک شی دلخواه را نمایش می دهد. روش نمایش // به عنوان یک آرگومان تابع تابع print1 (func، obj) (برای (n در obj) func (n + ":" + obj [n]) ارسال می شود؛) تابع print2 (func، objDevice، obj) ( برای (n در obj) func.call (objDevice, n + ":" + obj [n]);) var obj = (x: 5، y: 10); print2 (document.write, document, obj); // به درستی کار می کند print2 (console.log, console, obj); print1 (document.write, obj); // یک استثنای فراخوانی غیرقانونی ایجاد خواهد شد زیرا print1 (console.log، obj); // فراخوانی این متدها بدون شیء زمینه غیرممکن است

روش Bind ()

روش bind () برای اولین بار در ECMAScript 5 ظاهر شد، اما تقلید در ECMAScript 3 آسان است. همانطور که از نام آن پیداست، هدف اصلی متد bind () اتصال یک تابع به یک شی است. اگر متد bind () func را فراخوانی کنید و شیء obj را به آن ارسال کنید، تابع جدیدی برمی‌گرداند. فراخوانی تابع جدید (مانند یک تابع معمولی) تابع تابع اصلی را به عنوان روشی از obj فراخوانی می کند. هر آرگومان ارسال شده به تابع جدید به تابع اصلی ارسال می شود. برای مثال:

// تابع اتصال تابع func (y) (این را برگردانید.x + y;) var obj = (x: 1); // شیء برای اتصال به var g = func.bind (obj); // با فراخوانی g (x) obj.func (x) را فراخوانی می‌کند.

این روش اتصال در ECMAScript 3 آسان است، همانطور که در زیر نشان داده شده است:

// تابعی را برمی‌گرداند که func را به‌عنوان متد obj // فراخوانی می‌کند و همه آرگومان‌هایش را به تابع bind (func، obj) می‌دهد (اگر (func.bind) بازگشت func.bind (obj)؛ // از متد bind استفاده کنید، در صورت وجود else تابع بازگشت () (// Else bind مانند زیر بازگشت func.apply (obj، آرگومان ها)؛)

متد bind () در ECMAScript 5 فقط یک تابع را به یک شی متصل نمی کند. همچنین کاربرد جزئی را انجام می دهد: علاوه بر این مقدار، تمام آرگومان های ارسال شده به bind () پس از اولین آرگومان آن محدود می شوند. کاربرد جزئی یک تکنیک رایج در برنامه نویسی تابعی است و گاهی اوقات به آن می گویند کاری کردن.

مقاله در دست ساخت است!

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

تابع چیست؟

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

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

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

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

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

اعلام عملکرد و تماس

عملیات تابع در جاوا اسکریپت را می توان به 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 ("پیتر"); // پیتر تعریف نشده خوش آمدید // تابع sayWelcome را بدون ارسال آرگومان به آن فراخوانی کنید sayWelcome (); // خوش آمدید، تعریف نشده تعریف نشده

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

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

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

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

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

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

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

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

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

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

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

تابع mainF (p1، p2) (function childF () (console.log ("p1 =" + p1 + "; p2 = " + p2);) childF ();) mainF (3، 5); // p1 = 3; p2 = 5 اصلی F (4، 7)؛ // p1 = 4; p2 = 7

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

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

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

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

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

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

پارامترهای استراحت

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

// ... nums پارامترهای باقی مانده هستند که در این مورد با نام تابع nums doMath (mathAction, ... nums) قابل دسترسی هستند (var result = 0; nums.forEach (function (value) (switch (mathAction) ) ( مورد "جمع": نتیجه + = مقدار؛ شکست؛ مورد "sumCube": نتیجه + = مقدار ** 3؛ شکست؛ حالت "sumSquare": نتیجه + = مقدار ** 2؛ شکست؛ پیش فرض: نتیجه = 0. )) ) نتیجه را برگرداند؛) console.log (doMath ("جمع"، 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, anonymous user" را برمی گرداند؛ در غیر این صورت "Welcome," + userLastName + "" + userFirstName ; ) // اعلان متغیر person 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). جاوا اسکریپت - مقداری را از تابعی دریافت کنید که چیزی بر نمی گرداند

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

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

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

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

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

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

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

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

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

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

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

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

بازگشت

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

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

تابع واقعیت (n) (اگر (n === 1) (بازگشت 1؛) بازگشت واقعیت (n-1) * n;) console.log (fact (5)); // 120

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

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

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

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

// فراخوانی هشدار تابع ("متن")؛ جاوا اسکریپت - فراخوانی تابع هشدار

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

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

توابع فراخوانی

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

مربع (5)؛

دستور قبلی تابع را با آرگومان 5 فراخوانی می کند. تابع دستورات خود را اجرا می کند و مقدار 25 را برمی گرداند.

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

Console.log (مربع (5)); / * ... * / تابع مربع (n) (بازگشت n * n؛)

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

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

Console.log (مربع)؛ // مربع با مقدار اولیه تعریف نشده بالا می رود. console.log (مربع (5)); // TypeError: مربع یک تابع نیست var Square = تابع (n) (بازگشت n * n؛)

آرگومان های یک تابع به رشته ها و اعداد محدود نمی شود. شما می توانید اشیاء کامل را به یک تابع ارسال کنید. تابع show_props () (تعریف شده در) نمونه ای از تابعی است که یک شی را به عنوان آرگومان می گیرد.

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

تابع فاکتوریل (n) (اگر ((n === 0) || (n === 1)) بازگشت 1؛ در غیر این صورت بازگشت (n * فاکتوریل (n - 1))؛)

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

Var a, b, c, d, e; a = فاکتوریل (1)؛ // a مقدار 1 b = فاکتوریل (2) را می گیرد. // b مقدار 2 c = فاکتوریل (3) را دریافت می کند. // c مقدار 6 d = فاکتوریل (4) را دریافت می کند. // d مقدار 24 e = فاکتوریل (5) را دریافت می کند. // e مقدار 120 را دریافت می کند

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

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

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

// متغیرهای زیر در محدوده جهانی var num1 = 20, num2 = 3, name = "Chamahk" تعریف شده اند. // این تابع در تابع دامنه جهانی multiply () (return num1 * num2;) multiply (); // 60 را برمی گرداند // تابع نمونه تو در تو getScore () (var num1 = 2, num2 = 3؛ تابع add () (نام بازگشت + "scored" + (num1 + num2)؛) برگردان افزودن ();) getScore () // بازگشت "چمهک 5 گل"

محدوده و پشته تابع

بازگشت

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

  1. نام تابع
  2. یک متغیر درون دامنه که به تابع اشاره دارد

به عنوان مثال، تعریف تابع زیر را در نظر بگیرید:

Var foo = نوار تابع () (// عبارات به اینجا بروید);

در بدن تابع، موارد زیر همه معادل هستند:

  1. بار ()
  2. arguments.callee ()
  3. فوو ()

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

Var x = 0; در حالی که (x< 10) { // "x < 10" is the loop condition // do stuff x++; }

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

حلقه تابع (x) (اگر (x> = 10) // "x> = 10" شرط خروج است (معادل "! (X< 10)") return; // do stuff loop(x + 1); // the recursive call } loop(0);

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

تابع walkTree (node) (اگر (node ​​== null) // return؛ // کاری را با node برای (var i = 0; i) انجام دهید< node.childNodes.length; i++) { walkTree(node.childNodes[i]); } }

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

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

رفتار پشته مانند را می توان در مثال زیر مشاهده کرد:

تابع foo (i) (اگر (i< 0) return; console.log("begin: " + i); foo(i - 1); console.log("end: " + i); } foo(3); // Output: // begin: 3 // begin: 2 // begin: 1 // begin: 0 // end: 0 // end: 1 // end: 2 // end: 3

توابع تو در تو و بسته شدن

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

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

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

مثال زیر توابع تو در تو را نشان می دهد:

تابع addSquares (a, b) (تابع مربع (x) (بازگشت x * x;) برگردان مربع (a) + مربع (b)؛ a = addSquares (2, 3); // 13 را برمی گرداند b = addSquares (3, 4); // 25 c = addSquares (4، 5) را برمی گرداند. // 41 را برمی گرداند

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

تابع خارج (x) (تابع داخل (y) (بازگشت x + y;) بازگشت داخل؛) fn_inside = خارج (3); // اینطور فکر کنید: تابعی به من بدهید که 3 را به هر چیزی که می دهید اضافه کند // it result = fn_inside (5); // 8 نتیجه را برمی گرداند 1 = خارج (3) (5); // 8 را برمی گرداند

حفظ متغیرها

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

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

توابع چند تو در تو

توابع را می توان چند تو در تو، به عنوان مثال. یک تابع (A) حاوی تابع (B) حاوی تابع (C). هر دو تابع B و C در اینجا بسته می شوند، بنابراین B ​​می تواند به A دسترسی داشته باشد و C می تواند به B دسترسی پیدا کند. آنها به صورت بازگشتی شامل محدوده توابع حاوی آن هستند. به این می گویند زنجیره سازی دامنه... (چرا به آن "زنجیره" می گویند بعدا توضیح داده خواهد شد.)

به مثال زیر توجه کنید:

تابع A (x) (عملکرد B (y) (عملکرد C (z) (console.log (x + y + z)؛) C (3)؛) B (2)؛) A (1); // گزارش 6 (1 + 2 + 3)

در این مثال، C به B "s y و A" s x دسترسی دارد. این کار را می توان انجام داد زیرا:

  1. B یک بسته شامل A، یعنی. B می تواند به آرگومان ها و متغیرهای A دسترسی داشته باشد.
  2. C یک بسته شامل B را تشکیل می دهد.
  3. از آنجایی که B "s closure شامل A است، بسته شدن C" شامل A است، C می تواند به هر دو B دسترسی پیدا کند وآرگومان ها و متغیرهای A. به عبارت دیگر، C زنجیردامنه B و A به ترتیب.

معکوس اما درست نیست. A نمی تواند به C دسترسی داشته باشد، زیرا A نمی تواند به هیچ آرگومان یا متغیری از B که C متغیر آن است دسترسی داشته باشد. بنابراین، C فقط برای B خصوصی می ماند.

تضاد نام

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

تابع خارج () (var x = 5؛ تابع داخل (x) (بازگشت x * 2؛) بازگشت داخل؛) خارج () (10); // به جای 10 عدد 20 را برمی گرداند

تضاد نام در عبارت بازگشت x رخ می دهد و بین داخل "s پارامتر x و خارجی" متغیر x است. زنجیره دامنه در اینجا (درون، خارج، شی سراسری) است. بنابراین درون "s x" بر بیرون" s x اولویت دارد و 20 (داخل "s x) به جای 10 (خارج" s x) برگردانده می شود.

بسته شدن

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

Var pet = تابع (نام) (// تابع خارجی متغیری به نام "name" تعریف می کند var getName = تابع () (نام بازگشتی؛ // تابع داخلی به متغیر "name" تابع // خارجی دسترسی دارد) بازگشت getName؛ // تابع داخلی را برگردانید، در نتیجه آن را در معرض محدوده های بیرونی قرار دهید) myPet = pet ("Vivie"); myPet (); // "Vivie" را برمی‌گرداند

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

Var createPet = تابع (نام) (var جنسیت؛ بازگشت (setName: تابع (newName) (name = newName;)، getName: تابع () (نام بازگشت؛)، getSex: تابع () (جنس بازگشتی؛)، setSex: تابع (newSex) (اگر (نوع newSex === "رشته" && (newSex.toLowerCase () === "مذکر" || newSex.toLowerCase () === "مونث")) (جنس = newSex;)) )) var pet = createPet ("Vivie"); pet.getName (); // Vivie pet.setName ("الیور"); pet.setSex ("نر"); pet.getSex (); // مرد pet.getName (); // الیور

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

Var getCode = (تابع () (var apiCode = "0] Eal (eh & 2"؛ // کدی که نمی‌خواهیم خارجی‌ها بتوانند آن را تغییر دهند ... تابع برگرداندن () (return apiCode;)) () ؛ getCode ()؛ // apiCode را برمی گرداند

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

Var createPet = تابع (نام) (// تابع بیرونی متغیری به نام "name" را تعریف می کند. بازگشت (setName: function (name) (// تابع محصور شده نیز متغیری به نام "name" را تعریف می کند. Name = name; // چگونه به "نام" تعریف شده توسط تابع خارجی دسترسی پیدا کنیم؟)))

با استفاده از شیء آرگومان ها

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

استدلال [i]

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

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

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

تابع myConcat (جداکننده) (var result = ""؛ // مقداردهی اولیه لیست var i؛ // تکرار از طریق آرگومان ها برای (i = 1; i< arguments.length; i++) { result += arguments[i] + separator; } return result; }

شما می توانید هر تعداد آرگومان را به این تابع ارسال کنید و هر آرگومان را در یک رشته "list" الحاق می کند:

// "قرمز، نارنجی، آبی"، myConcat ("، "قرمز"، "نارنجی"، "آبی") را برمی گرداند. // برمی گرداند "فیل؛ زرافه؛ شیر؛ یوزپلنگ؛" myConcat (";"، "فیل"، "زرافه"، "شیر"، "یوزپلنگ"); // برمی گرداند "مریم گلی. ریحان. پونه کوهی. فلفل. جعفری." myConcat (."، "Sage", "ریحان"، "اورگانو"، "فلفل"، "جعفری");

توجه داشته باشید:متغیر آرگومان ها "آرایه مانند" است، اما آرایه نیست. این آرایه مانند است که دارای یک شاخص شماره و یک ویژگی طول است. با این حال، همه روش های دستکاری آرایه را ندارد.

دو عامل بر معرفی توابع پیکان تأثیر گذاشت: توابع کوتاهتر و غیر الزام آور بودن این.

عملکردهای کوتاهتر

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

Var a = ["هیدروژن"، "هلیوم"، "لیتیوم"، "بریلیم"]; var a2 = a.map (تابع (ها) (بازگشت s.length؛)); console.log (a2); // logs var a3 = a.map (s => s.length); console.log (a3); // سیاهههای مربوط

اینو جدا نکن

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

Function Person () (// سازنده Person () "this" را به عنوان خودش تعریف می کند.this.age = 0؛ setInterval (function growUp () (// در حالت غیر محدود، تابع growUp () این را تعریف می کند. شی سراسری، که با "this" // تعریف شده توسط Person () constructor.this.age ++;), 1000؛) var p = new Person ();

در ECMAScript 3/5، این مشکل با تخصیص مقدار در این به متغیری که می‌توانست روی آن بسته شود، برطرف شد.

Function Person () (var self = this; // برخی "that" را به جای "self" انتخاب می کنند. // یکی را انتخاب کنید و be consent.self.age = 0؛ setInterval (function growUp () (// callback اشاره به متغیر `self` که // مقدار مورد انتظار شیء است.self.age ++;)، 1000)؛)

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

Var add = تابع (arg1, arg2) (var sum = arg1 + arg2; return sum;) var result = add (5, 2); // نتیجه اکنون 7 است

یعنی تابع، اول از همه، نامی ندارد. ثانیاً، به یک متغیر اختصاص داده می شود، اما نه فقط اختصاص داده می شود، بلکه بدنه آن بلافاصله می رود. شخصاً برای من که قبلاً به زبان هایی مانند VB، C ++ نوشته بودم، چنین اعلانی باعث سردرگمی و سوء تفاهم در مورد نحوه کار و اینکه اصلاً چرا آن را اینگونه بنویسید.

من به اعلان و فراخوانی تابع "کلاسیک" مانند این عادت کرده ام:

تابع add (arg1, arg2) (var sum = arg1 + arg2; return sum;) var result = add (5, 3); // نتیجه اکنون 8 است

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

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

Var a = 5; var b = a; هشدار (ب)؛ // 5 را چاپ خواهد کرد

چیز معمولی حالا به این کد نگاه کنید:

Var add = تابع (arg1, arg2) (var sum = arg1 + arg2; return sum;) var calcSum = add; هشدار (calcSum (5، 6))؛ // چاپ 11

آیا در حال حاضر شروع به حدس زدن کرده اید؟ از آنجایی که یک تابع مانند یک متغیر است، می‌توانیم آن را با انتساب معمولی در متغیرهای دیگر «ضرب» کنیم و آنها را نیز به توابع تبدیل کنیم. اکنون calcSum می تواند دو عدد را نیز اضافه کند. با این حال کد

Var calcSum = افزودن (1، 1); // calcSum اکنون برابر با 2 است، این یک تابع نیست، بلکه یک متغیر با یک هشدار عددی است (calcSum (5, 6)); //خطا

اجرا نخواهد شد، زیرا در خط اول نه خود تابع، بلکه نتیجه اجرای آن را اختصاص دادیم (پرانتز نشان می دهد که ما باید تابع را اجرا کنیم، نه تخصیص آن).

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

Var calcFact = تابع واقعیت (val) (اگر (val == 1)؟ Val: val * fact (val - 1)؛ // محاسبه فاکتوریل با استفاده از بازگشت) هشدار (calcFact (4)); // چاپ 24

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

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

Var date = تاریخ جدید (); var hello = (date.getHours ()< 12) ? function() {alert("Доброе утро!")} : (date.getHours() < 18) ? function() {alert("Добрый день!")} : function() {alert("Добрый вечер!")}; hello();

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

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

عملکرد صبح بخیر () (هشدار ("صبح بخیر!")؛) عملکرد خوب بعد از ظهر () (هشدار ("بعدازظهر بخیر!")؛) عملکرد خوب عصر () (هشدار ("عصر بخیر!")؛) تاریخ متغیر = تاریخ جدید () (date.getHours ()< 12) ? goodMorning() : (date.getHours() < 18) ? goodAfternoon() : goodEvning();

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

ثانیاً، اگر از روش "کلاسیک" استفاده کنیم، توانایی اختصاص یک تابع به یک متغیر را از دست می دهیم. یعنی بنویس

تابع add (a, b) (برگرداندن a + b;) var calcSum = add; calcSum (5، 5);

دیگر امکان پذیر نیست. بنابراین، در مثال ما، اگر باز هم نیاز به احوالپرسی بیش از یک بار به مهمان داشته باشیم، باید هر بار این قطعه را کپی کنیم:

(date.getHours ()< 12) ? goodMorning() : (date.getHours() < 18) ? goodAfternoon() : goodEvning();

و در مورد اول، نوشتن فقط hello (); و نتیجه یکسان خواهد بود.

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

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

ایجاد توابع

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

توابع - اشیاء

در جاوا اسکریپت، توابع اشیاء تمام عیار از کلاس Function داخلی هستند. به همین دلیل است که می توان آنها را به متغیرها اختصاص داد، پاس داد و البته دارای ویژگی هایی بود:

تابع f () (...) f.test = 6 ... هشدار (f.test) // 6

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

برای مثال،

تابع func () (var funcObj = arguments.callee funcObj.test ++ هشدار (funcObj.test)) func.test = 1 func () func ()

در ابتدا، هر تابع یک متغیر آرگومان در درون خود ایجاد می کند و به arguments.callee یک مرجع به خود اختصاص می دهد. بنابراین arguments.callee.test یک ویژگی func.test است، یعنی آزمون متغیر استاتیک.

در مثال، تکلیف نمی تواند انجام شود:

تست Var = arguments.callee.test تست ++

زیرا در این مورد، عملیات ++ روی تست متغیر محلی کار می‌کرد، نه روی ویژگی تست شی تابع.

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

محدوده ها

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

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

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

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

برای مثال:

تابع a () (z = 5 // z را به صورت محلی تغییر دهید .. // .. زیرا z از طریق var var z اعلام شده است) // تست حذف z // پاک کردن za جهانی () فقط در صورت هشدار (window.z) // => تعریف نشده است زیرا z به صورت محلی تغییر کرده است

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

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

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

تابع زیر زمان لازم برای طی مسافت مسافتی را با سرعت یکنواخت برمی گرداند.

در اولین راه اندازی، این تابع با آرگومان های فاصله = 10، سرعت = تعریف نشده کار می کند. به طور معمول، این وضعیت، اگر توسط تابع پشتیبانی شود، یک مقدار پیش فرض را ارائه می دهد:

// اگر سرعت یک مقدار نادرست است (تعریف نشده، 0، نادرست ...) - جایگزین 10 سرعت = سرعت || 10

اپراتور || در جاوا اسکریپت true/false را بر نمی گرداند، بلکه خود مقدار را برمی گرداند (اولین مقدار که به true داده می شود).

بنابراین، برای تنظیم مقادیر پیش فرض استفاده می شود. در تماس ما، سرعت تعریف نشده خواهد بود || 10 = 10.

بنابراین، نتیجه 10/10 = 1 خواهد بود.

پرتاب دوم استاندارد است.

اجرای سوم چندین آرگومان اضافی را ارائه می دهد. این تابع کار با آرگومان های اضافی را فراهم نمی کند، بنابراین آنها به سادگی نادیده گرفته می شوند.

خوب، در مورد دوم، هیچ آرگومانی وجود ندارد، بنابراین فاصله = تعریف نشده است، و نتیجه تقسیم نامشخص است / 10 = NaN (Not-A-Number، یک خطا رخ داده است).

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

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

  1. آرگومان هایی را که از صفر شروع می شوند فراخوانی کنید
  2. طول در ویژگی length
  3. ارجاع به خود تابع در ویژگی callee

برای مثال،

تابع func () (برای (var i = 0; i

خاصیت arguments مانند یک آرایه است که دارای طول و شاخص های عددی است. در واقع، آرگومان ها به کلاس Array تعلق ندارند و متدهای آن مانند push، pop و غیره را شامل نمی شوند.

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

Var args = Array.prototype.slice.call (arguments) // .. args اکنون یک آرایه واقعی از آرگومان ها است. args.shift () ...

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

Var func = تابع (a, b) (هشدار (a + b)) var arr = func.apply (null, arr) // => هشدار (3)

نمونه ای از انتقال یک تابع با مرجع

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

برای مثال، map تابع func را می گیرد، آن را به هر عنصر در آرایه arr اعمال می کند و آرایه حاصل را برمی گرداند:

Var map = تابع (func، arr) (var result = for (var i = 0; i

مثال استفاده:

نقشه (اجرا،) // =

یا می‌توانید یک تابع ناشناس را مستقیماً در فراخوانی نقشه ایجاد کنید:

// تابع ناشناس نقشه اعداد را سه برابر می کند (عملکرد (a) (برگرداندن a * 3)،) // =

تا کردن پارامترها در یک شی

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

برای مثال:

// شما می توانید تنها بخشی از آرگومان ها را مشخص کنید // مشخص نشده است - با تغییر اندازه تابع پیش فرض محاسبه یا گرفته می شوند (toWidth, toHeight, saveProportions, animate) (// مقادیر پیش فرض saveProportions = saveProportions || true animate = animate | | واقعی toHeight = toHeight | | ...)

تماس با پارامترهای اختیاری باید به این صورت انجام شود:

تغییر اندازه (100، null، null، true)

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

تغییر اندازه تابع (تنظیم) (// مقادیر پیش‌فرض var saveProportions = setup.saveProportions || true var animate = setup.animate || var toHeight = setup.toHeight || ...)

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

تنظیم Var = (به عرض: 100، متحرک: واقعی) تغییر اندازه (تنظیم) // یا تغییر اندازه ((به عرض: 100، متحرک: واقعی))

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

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

Var setup = (toWidth: 100، animate: true، saveProportions: false) resize (setup) setup.toWidth = 200 resize (setup)

مقالات مرتبط برتر