شما یاد گرفته اید که ما می توانیم توابع تو در تو (nested functions) در جاوا اسکریپت ایجاد کنیم. تابع داخلی می تواند به متغیرها و پارامترهای یک تابع خارجی دسترسی داشته باشد (اما، نمی تواند به آرگومان های شی تابع خارجی دسترسی پیدا کند). مثال زیر را در نظر بگیرید.
در مثال بالا، 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
منابع:
ثبت دیدگاه جدید
0 دیدگاه
نشانی ایمیل شما منتشر نخواهد شد. بخشهای موردنیاز علامتگذاری شدهاند *