closure در جاوا اسکریپت

closure در جاوا اسکریپت

Closure  به این معنی است که یک تابع داخلی همیشه به متغیرها و پارامترهای تابع outer خود دسترسی دارد، حتی پس از return تابع outer .
 
شما یاد گرفته اید که ما می توانیم توابع تو در تو (nested functions) در جاوا اسکریپت ایجاد کنیم. تابع داخلی می تواند به متغیرها و پارامترهای یک تابع خارجی دسترسی داشته باشد (اما، نمی تواند به آرگومان های شی تابع خارجی دسترسی پیدا کند). مثال زیر را در نظر بگیرید.
 
function OuterFunction() {

    var outerVariable = 1;

    function InnerFunction() {
        alert(outerVariable);
    }

    InnerFunction();
}
 
در مثال بالا، InnerFunction() می تواند به outerVariable دسترسی داشته باشد.
 
اکنون، طبق تعریف بالا، InnerFunction() می تواند به outerVariable دسترسی داشته باشد، حتی اگر جداگانه اجرا شود. مثال زیر را در نظر بگیرید.
 
function OuterFunction() {

    var outerVariable = 100;

    function InnerFunction() {
        alert(outerVariable);
    }

    return InnerFunction;
}
var innerFunc = OuterFunction();

innerFunc(); // 100
 
در مثال بالا، InnerFunction را return کنید . با فراخوانی OuterFunction() فانکشن InnerFunction را از OuterFunction برمی گرداند. متغیر innerFunc فقط به InnerFunction() اشاره می کند، نه به OuterFunction(). بنابراین اکنون، وقتی innerFunc() را فرا می‌خوانید، همچنان می‌تواند به outerVariable که در OuterFunction () اعلام شده است دسترسی داشته باشد. به این می گویند Closure.
 
یکی از ویژگی های مهم closure  این است که متغیرهای بیرونی می توانند حالت های خود را بین فراخوانی های متعدد حفظ کنند. به یاد داشته باشید، تابع inner کپی جداگانه متغیرهای outer  را نگه نمی دارد، بلکه به متغیرهای outer ارجاع می دهد، به این معنی که اگر آن را با استفاده از تابع inner تغییر دهید، مقدار متغیرهای outer تغییر می کند.
 
function Counter() {
    var counter = 0;

    function IncreaseCounter() {
        return counter += 1;
    };

    return IncreaseCounter;
}

var counter = Counter();
alert(counter()); // 1
alert(counter()); // 2
alert(counter()); // 3
alert(counter()); // 4
 
در مثال بالا، تابع خارجی Counter تابع داخلی IncreaseCounter() را برمی گرداند. IncreaseCounter شمارنده متغیر خارجی را به یک افزایش می دهد. بنابراین، فراخوانی تابع داخلی چند بار، شمارنده را هر بار به یک افزایش می دهد.
 
Closure  در سطوح مختلف تابع های داخلی معتبر است.
 
function Counter() {
    
    var counter = 0;

    setTimeout( function () {
        var innerCounter = 0;
        counter += 1;
        alert("counter = " + counter);

        setTimeout( function () {
            counter += 1;
            innerCounter += 1;
            alert("counter = " + counter + ", innerCounter = " + innerCounter)
        }, 500);

    }, 1000);
};

Counter();
 
 
طبق تعریف closure ، اگر تابع داخلی به متغیرهای تابع بیرونی دسترسی داشته باشد، تنها به آن closure می گویند.
 
مورد زیر closure نیست.
 
var Counter = (function () {
        var i = 0;
        return { counter : i += 1 };
})();
 
 
چه زمانی از Closure استفاده کنیم؟
 
Closure در پنهان کردن جزئیات پیاده سازی در جاوا اسکریپت مفید است. به عبارت دیگر، ایجاد variables ها یا function خصوصی می تواند مفید باشد.
 
مثال زیر نحوه ایجاد توابع و متغیر خصوصی را نشان می دهد.

 
var counter = (function() {
  var privateCounter = 0;
  function changeBy(val) {
    privateCounter += val;
  }
  return {
    increment: function() {
      changeBy(1);
    },
    decrement: function() {
      changeBy(-1);
    },
    value: function() {
      return privateCounter;
    }
  };   
})();

alert(counter.value()); // 0
counter.increment();
counter.increment();
alert(counter.value()); // 2
counter.decrement();
alert(counter.value()); // 1
 
 
منابع:
 
نویسنده :
مجید پورداود
  • مجید پورداود
  • مهندس نرم افزار و تحلیلگر ارشد سیستم های کامپیوتری تحت وب می باشم. از سال 1395 برنامه نویسی را شروع کردم و به زبان های php (فریم ورک laravel -codeigniter)  و زبان جاوا اسکریپت (فریم ورک express.js-nest.js)  تسلط دارم.  

ثبت دیدگاه جدید

0 دیدگاه

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *