شما اینجا هستید

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

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

// The following variables are defined in the global scope
var num1 = 20,
    num2 = 3,
    name = "Chamahk";

// This function is defined in the global scope
function multiply() {
  return num1 * num2;
}

multiply(); // Returns 60

// A nested function example
function getScore () {
  var num1 = 2,
      num2 = 3;
  
  function add() {
    return name + " scored " + (num1 + num2);
  }
  
  return add();
}

getScore(); // Returns "Chamahk scored 5"

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

توابع بازگشتی

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

  1. نام تابع

  2. ()arguments.callee در درسهای بعد توضیح داده میشود

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

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

var foo = function bar() {
   // statements go here
};

درون بدنه تابع، موارد زیر میتواند وجود داشته باشد:

  1. ()bar

  2. ()arguments.callee

  3. ()foo

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

var x = 0;
while (x < 10) { // "x < 10" is the loop condition
   // do stuff
   x++;
}

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

function loop(x) {
  if (x >= 10) // "x >= 10" is the exit condition (equivalent to "!(x < 10)")
    return;
  // do stuff
  loop(x + 1); // the recursive call
}
loop(0);

 

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

function walkTree(node) {
  if (node == null) // 
    return;
  // do something with node
  for (var i = 0; i < node.childNodes.length; i++) {
    walkTree(node.childNodes[i]);
  }
}

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

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

function foo(i) {
  if (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

 

توابع تودرتو و بستار

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

چونکه تابع تو در تو یک بستار است‌، به این معنی است که تابع تو در تو میتواند متغیرها و آرگومانهای تابعی که درون آن قرار دارد (والد) را به ارث ببرد.

به طور خلاصه:

  • تابع درونی فقط میتواند به اعلانات تابع بیرونی دسترسی داشته باشد.

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

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

function addSquares(a,b) {
  function square(x) {
    return x * x;
  }
  return square(a) + square(b);
}
a = addSquares(2,3); // returns 13
b = addSquares(3,4); // returns 25
c = addSquares(4,5); // returns 41

 

در مثال بالا یک تابع به نام square درون تابع addsquare تعریف کرده ایم سپس یک بار تابع square(a) و یکبار هم تابع square(b) را فراخوانی میکنیم و با هم جمع میکنیم. همانطور که ملاحظه میکنید از آرگومانهای تابع addsquare(a,b) در تابع square(x) استفاده کرده ایم.

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

function outside(x) {
  function inside(y) {
    return x + y;
  }
  return inside;
}
fn_inside = outside(3); // Think of it like: give me a function that adds 3 to whatever you give it
result = fn_inside(5); // returns 8

result1 = outside(3)(5); // returns 8

توابع تو در توی چندگانه

توابع میتوانند به صورت چندگانه، تو در تو باشند، برای مثال function (A) شامل function (B) و function (B) هم شامل function (C) است. توابع B و C در اینجا به شکل بستار هستند، بنابراین B میتواند به A دسترسی داشته باشد و C به A دسترسی داشته باشد. بعلاوه،‌ چونکه C میتواند به B دسترسی داشته باشد پس به A هم دسترسی دارد. بنابراین بستارها میتوانند شامل چندین حوزه (‌اسکوپ) باشند؛ این شیوه، زنجیره دامنه (scope chaining) نام دارد.

مثال زیر را در نظر بگیرید:

function A(x) {
  function B(y) {
    function C(z) {
      console.log(x + y + z);
    }
    C(3);
  }
  B(2);
}
A(1); // logs 6 (1 + 2 + 3)

 

در این مثال C به آرگوان y تابع B و آرگومان x تابع A دسترسی دارد. این برنامه کار درست کار میکند چون:

  1. B به صورت یک بستار در A است،‌ مثلا B میتواند به آرگوانها و متغیرهای A دسترسی داشته باشد.

  2. C به شکل بستار درون ‌B است.

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

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

تداخل نام

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

function outside() {
  var x = 10;
  function inside(x) {
    return x;
  }
  return inside;
}
result = outside()(20); // returns 20 instead of 10

تداخل نام در هنگام اجرای دستور return x بین پارامتر x درونی و متغیر x بیرونی اتفاق می افتد. در اینجا زنجیره دامنه به صورت {inside, outside,global object} است. بنابراین x درونی اولویت بیشتری نسبت به x بیرونی دارد و 20 x درونی به جای 10 x بیرونی بازگردانده میشود.

دیدگاه‌ها

ممنون

Kamagra Online Pharmacy Uk order on line levitra Proper Dosing Of Cephalexin Generic Viagra Pill In Usa

افزودن دیدگاه جدید

دیدگاه

  • تگ‌های HTML مجاز: <a> <em> <strong> <cite> <blockquote> <code> <ul> <ol> <li> <dl> <dt> <dd> <img>
  • خطوط و پاراگراف‌ها بطور خودکار اعمال می‌شوند.
  • نشانی صفحه‌ها وب و پست الکترونیک بصورت خودکار به پیوند تبدیل می‌شوند.

Plain text

  • تگ‌های HTML مجاز نیستند.
  • نشانی صفحه‌ها وب و پست الکترونیک بصورت خودکار به پیوند تبدیل می‌شوند.
  • خطوط و پاراگراف‌ها بطور خودکار اعمال می‌شوند.
كد امنيتي
این پرسش برای جلوگیری از ارسال اسپمهای اتوماتیک است.