প্রতিবার এবং পরে আমি "ক্লোজার" উল্লেখ করা দেখছি, এবং আমি এটি দেখার চেষ্টা করেছি কিন্তু উইকি এমন একটি ব্যাখ্যা দেয় না যা আমি বুঝতে পেরেছি। এখানে কেউ আমাকে সাহায্য করতে পারে?
প্রতিবার এবং পরে আমি "ক্লোজার" উল্লেখ করা দেখছি, এবং আমি এটি দেখার চেষ্টা করেছি কিন্তু উইকি এমন একটি ব্যাখ্যা দেয় না যা আমি বুঝতে পেরেছি। এখানে কেউ আমাকে সাহায্য করতে পারে?
উত্তর:
(অস্বীকৃতি: এটি একটি প্রাথমিক ব্যাখ্যা; সংজ্ঞা যতদূর যায় আমি কিছুটা সরল করছি)
ক্লোজারটি ভাবার সর্বাধিক সহজ উপায় হ'ল একটি ফাংশন যা একটি ভেরিয়েবল হিসাবে সংরক্ষণ করা যেতে পারে ("প্রথম শ্রেণির ফাংশন" হিসাবে পরিচিত), এতে অন্যান্য ভেরিয়েবল স্থানীয়ভাবে এটি তৈরির সুযোগে অ্যাক্সেস করার বিশেষ ক্ষমতা রাখে।
উদাহরণ (জাভাস্ক্রিপ্ট):
var setKeyPress = function(callback) {
document.onkeypress = callback;
};
var initialize = function() {
var black = false;
document.onclick = function() {
black = !black;
document.body.style.backgroundColor = black ? "#000000" : "transparent";
}
var displayValOfBlack = function() {
alert(black);
}
setKeyPress(displayValOfBlack);
};
initialize();
ক্রিয়াকলাপ 1 নিযুক্ত document.onclick
এবং displayValOfBlack
বন্ধ হয়। আপনি দেখতে পাচ্ছেন যে তারা উভয়ই বুলিয়ান ভেরিয়েবলটি উল্লেখ করে black
তবে সেই ভেরিয়েবলটি ফাংশনের বাইরে নির্ধারিত হয়। কারণ black
হল সুযোগ যেখানে ফাংশন সংজ্ঞায়িত করা হয় স্থানীয় , এই পরিবর্তনশীল পয়েন্টার সংরক্ষিত হয়।
আপনি যদি এইচটিএমএল পৃষ্ঠায় রাখেন:
এটি দেখায় যে উভয়েরই অ্যাক্সেস একইরকম black
এবং কোনও মোড়কযুক্ত বস্তু ছাড়াই রাষ্ট্র সঞ্চয় করতে ব্যবহার করা যেতে পারে ।
কলটি setKeyPress
হ'ল যে কোনও ফাংশন ঠিক যেমন কোনও ভেরিয়েবলের মতো কীভাবে পাশ করা যায় তা প্রদর্শন করা। সুযোগ অবসান সংরক্ষিত এখনও এক যেখানে ম ফাংশন পূর্বনির্ধারণ হয়।
বন্ধগুলি ইভেন্ট হ্যান্ডলার হিসাবে সাধারণত ব্যবহৃত হয়, বিশেষত জাভাস্ক্রিপ্ট এবং অ্যাকশনস্ক্রিপ্টে। ক্লোজারগুলির ভাল ব্যবহার আপনাকে অবজেক্ট র্যাপার তৈরি না করে ইভেন্ট হ্যান্ডলারগুলিতে সুস্পষ্টভাবে বেঁধে রাখতে সহায়তা করবে। তবে, অসাবধান ব্যবহারের ফলে মেমোরি ফাঁস হতে পারে (যেমন যখন কোনও অব্যবহৃত তবে সংরক্ষিত ইভেন্ট হ্যান্ডলার কেবল মেমরির বৃহত অবজেক্টগুলিতে বিশেষত ডিওএম অবজেক্টগুলিকে ধরে রাখতে পারে, আবর্জনা সংগ্রহ রোধ করে)।
1: আসলে, জাভাস্ক্রিপ্টের সমস্ত ফাংশন ক্লোজার।
black
কোনও ফাংশনের অভ্যন্তরে ঘোষণা করা হয়েছে, তাই স্ট্যাকটি আনইন্ডিংস হিসাবে ধ্বংস হবে না ...?
black
কোনও ফাংশনের অভ্যন্তরে ঘোষণা করা হয়েছে, তাই এটি ধ্বংস হবে না " said এও মনে রাখবেন যে আপনি যদি কোনও ফাংশনে কোনও অবজেক্ট ঘোষণা করেন এবং তারপরে এটি অন্য কোনও স্থানে বাস করে এমন একটি ভেরিয়েবলের কাছে অর্পণ করেন তবে সেই বস্তুটি সংরক্ষিত রয়েছে কারণ এর সাথে অন্যান্য উল্লেখ রয়েছে।
একটি ক্লোজারটি মূলত কোনও অবজেক্টের দিকে তাকানোর আলাদা উপায়। একটি অবজেক্ট এমন ডেটা যা এর সাথে আবদ্ধ এক বা একাধিক ফাংশন। ক্লোজার হ'ল এমন একটি ফাংশন যা এর সাথে আবদ্ধ এক বা একাধিক ভেরিয়েবল। কমপক্ষে বাস্তবায়ন স্তরে দুটি মূলত অভিন্ন। আসল পার্থক্য তারা কোথা থেকে এসেছে in
অবজেক্ট-ওরিয়েন্টেড প্রোগ্রামিংয়ে আপনি কোনও অবজেক্ট শ্রেণির সদস্যপদ ভেরিয়েবল এবং এর পদ্ধতিগুলি (সদস্য ফাংশন) আপ-ফ্রন্ট সংজ্ঞায়িত করে এবং তারপরে আপনি সেই শ্রেণীর উদাহরণ তৈরি করেন। প্রতিটি উদাহরণ কনস্ট্রাক্টর সূচনা করে সদস্য ডেটার একটি অনুলিপি নিয়ে আসে। তারপরে আপনার কাছে কোনও অবজেক্টের ধরণের ভেরিয়েবল রয়েছে এবং এটিকে ডেটা টুকরো হিসাবে পাস করে দিন, কারণ ফোকাসটি ডেটা হিসাবে তার প্রকৃতির দিকে থাকে।
অন্যদিকে, বন্ধ হয়ে গেলে, অবজেক্টটি কোনও শ্রেণীর মতো আপ-ফ্রন্টকে সংজ্ঞায়িত করা হয় না বা আপনার কোডে কনস্ট্রাক্টর কলের মাধ্যমে ইনস্ট্যান্টিয়েটেড হয় না। পরিবর্তে, আপনি অন্য ফাংশনের অভ্যন্তরের ফাংশন হিসাবে ক্লোজারটি লিখবেন। বন্ধটি বাইরের ফাংশনের যেকোন স্থানীয় ভেরিয়েবলকে নির্দেশ করতে পারে এবং সংকলক এটি সনাক্ত করে এবং এই পরিবর্তনকগুলি বহিরাগত ফাংশনের স্ট্যাক স্থান থেকে বন্ধের গোপন অবজেক্ট ঘোষণায় স্থানান্তরিত করে। তারপরে আপনার একটি ক্লোজার টাইপের একটি ভেরিয়েবল রয়েছে এবং এটি মূলত হুডের নীচে কোনও অবজেক্ট হলেও আপনি এটি একটি ফাংশন রেফারেন্স হিসাবে ঘুরিয়ে দেন, কারণ ফাংশন হিসাবে তার প্রকৃতির দিকে ফোকাস রয়েছে।
মেয়াদ অবসান আসলে কোড (ব্লক, ফাংশন) এক টুকরা বিনামূল্যে ভেরিয়েবল যে থাকতে পারে যে থেকে আসে বন্ধ (অর্থাত একটি মান আবদ্ধ) পরিবেশ যা কোডের ব্লক সংজ্ঞায়িত করা হয় দ্বারা।
উদাহরণস্বরূপ স্কেলা ফাংশন সংজ্ঞাটি ধরুন:
def addConstant(v: Int): Int = v + k
ফাংশন বডিটিতে দুটি নাম (ভেরিয়েবল) v
এবং k
দুটি পূর্ণসংখ্যার মান নির্দেশ করে। নামটি v
আবদ্ধ কারণ এটি ফাংশনটির আর্গুমেন্ট হিসাবে ঘোষিত হয়েছে addConstant
(ফাংশন ঘোষণার দিকে তাকিয়ে আমরা জানি যে v
ফাংশনটি চালু করার সময় একটি মান নির্ধারিত হবে)। নামটি k
নিখরচায় ফাংশন করে addConstant
কারণ ফাংশনে কোনও মানটি k
(এবং কীভাবে) আবদ্ধ সে সম্পর্কে কোনও ধারণা নেই ।
যেমন একটি কল মূল্যায়ন করার জন্য:
val n = addConstant(10)
আমাদের k
একটি মান নির্ধারণ করতে হবে, যা কেবল তখনই ঘটতে পারে যখন নামটি k
প্রসঙ্গে addConstant
সংজ্ঞায়িত করা হয়। উদাহরণ স্বরূপ:
def increaseAll(values: List[Int]): List[Int] =
{
val k = 2
def addConstant(v: Int): Int = v + k
values.map(addConstant)
}
এখন আমরা addConstant
একটি প্রসঙ্গে যেখানে k
সংজ্ঞায়িত করা addConstant
হয়েছে তা সংজ্ঞায়িত করেছি, এটি একটি বন্ধ হয়ে গেছে কারণ এর সমস্ত ফ্রি ভেরিয়েবল এখন বন্ধ হয়ে গেছে (একটি মানের সাথে আবদ্ধ): addConstant
এটি অনুরোধ করা যেতে পারে এবং এটি কোনও ফাংশন হিসাবে ঘুরতে পারে। ক্লোজারটি সংজ্ঞায়িতk
হওয়ার পরে মুক্ত ভেরিয়েবলটি একটি মানের সাথে আবদ্ধ হয় তা নোট করুন , যখন ক্লোজারটি আহ্বান করা হলে আর্গুমেন্ট ভেরিয়েবলটি আবদ্ধ হয় ।v
সুতরাং একটি ক্লোজারটি মূলত একটি ফাংশন বা কোড ব্লক যা প্রসঙ্গ দ্বারা আবদ্ধ হওয়ার পরে এটির মুক্ত ভেরিয়েবলের মাধ্যমে অ-স্থানীয় মানগুলিতে অ্যাক্সেস করতে পারে।
অনেক ভাষায়, আপনি যদি একবার বন্ধ ব্যবহার করেন তবে একবার এটি বেনামে রাখতে পারেন , যেমন
def increaseAll(values: List[Int]): List[Int] =
{
val k = 2
values.map(v => v + k)
}
নোট করুন যে কোনও ফ্রি ভেরিয়েবলগুলি নেই এমন একটি ফাংশন হ'ল বন্ধের একটি বিশেষ কেস (বিনামূল্যে ভেরিয়েবলের খালি সেট সহ)। আনুষাঙ্গিকভাবে, একটি বেনামে ফাংশন একটি বেনামে বন্ধের একটি বিশেষ ক্ষেত্রে , অর্থাত্ একটি বেনাম ফাংশন কোনও বেনামে কোনও মুক্ত ভেরিয়েবল নেই closure
জাভাস্ক্রিপ্টের একটি সহজ ব্যাখ্যা:
var closure_example = function() {
var closure = 0;
// after first iteration the value will not be erased from the memory
// because it is bound with the returned alertValue function.
return {
alertValue : function() {
closure++;
alert(closure);
}
};
};
closure_example();
alert(closure)
এর পূর্বে নির্মিত মান ব্যবহার করবে closure
। ফিরে আসা alertValue
ফাংশনটির নামস্থানটি সেই স্থানের সাথে যুক্ত হবে যেখানে closure
ভেরিয়েবলটি থাকে। আপনি যখন পুরো ফাংশনটি মুছবেন তখন closure
ভেরিয়েবলের মান মুছে যাবে তবে ততক্ষণ পর্যন্ত alertValue
ফাংশনটি সর্বদা ভেরিয়েবলের মান পড়তে / লিখতে সক্ষম হবে closure
।
আপনি যদি এই কোডটি চালনা করেন তবে প্রথম পুনরাবৃত্তিটি closure
ভেরিয়েবলের 0 মান প্রদান করবে এবং এতে ফাংশনটি পুনরায় লিখবে:
var closure_example = function(){
alertValue : function(){
closure++;
alert(closure);
}
}
এবং ফাংশনটি সম্পাদন করতে alertValue
স্থানীয় ভেরিয়েবলের প্রয়োজন হওয়ায় closure
এটি পূর্বে নির্ধারিত স্থানীয় ভেরিয়েবলের মানের সাথে আবদ্ধ হয় closure
।
এবং এখন আপনি যখনই closure_example
ফাংশনটি কল করবেন তখন এটি closure
ভেরিয়েবলের বর্ধিত মানটি লিখবে কারণ alert(closure)
আবদ্ধ।
closure_example.alertValue()//alerts value 1
closure_example.alertValue()//alerts value 2
closure_example.alertValue()//alerts value 3
//etc.
একটি "ক্লোজার" হ'ল সংক্ষেপে কিছু স্থানীয় রাষ্ট্র এবং কিছু কোড প্যাকেজের সাথে একত্রিত হয়। সাধারণত, স্থানীয় রাষ্ট্রটি একটি আশেপাশের (লেক্সিকাল) স্কোপ থেকে আসে এবং কোডটি (মূলত) একটি অভ্যন্তরীণ ফাংশন হয় যা পরে বাইরে ফিরে আসে। বন্ধ হ'ল অভ্যন্তরীণ ফাংশনটি দেখায় এবং অভ্যন্তরীণ ফাংশনের কোডটি ক্যাপচারড ভেরিয়েবলগুলির সংমিশ্রণ।
দুর্ভাগ্যক্রমে, অপরিচিত থাকার কারণে এটি ব্যাখ্যা করা কিছুটা কঠিন It's
অতীতে সফলভাবে ব্যবহৃত একটি উপমাটি ছিল "ধারণা করুন আমাদের কাছে এমন কিছু আছে যা আমরা 'বই' বলি, রুম-ক্লোজারে, 'বই' হ'ল সেই অনুলিপিটি সেখানে, কোণে, টিএওসিপি-র, কিন্তু টেবিল-ক্লোজারে রয়েছে এটি কোনও ড্রেসডেন ফাইলের বইয়ের অনুলিপি So সুতরাং আপনি কী বন্ধ হয়ে আছেন তার উপর নির্ভর করে কোডটি 'আমাকে বইটি দাও' এর ফলে বিভিন্ন জিনিস ঘটবে results
static
স্থানীয় ভেরিয়েবল সহ সি ফাংশনকে কি বন্ধ হিসাবে বিবেচনা করা যেতে পারে? হাস্কেল বন্ধের সাথে কি রাষ্ট্র জড়িত?
static
স্থানীয় ভেরিয়েবল সহ একক ফাংশন থেকে একাধিক ক্লোজার তৈরি করতে সক্ষম হতে চান ), আপনার ঠিক একটি রয়েছে।
'রাষ্ট্র' ধারণাটি সংজ্ঞায়িত না করে বন্ধ কী কী তা নির্ধারণ করা শক্ত।
মূলত, সম্পূর্ণ লেজিকাল স্কোপিংয়ের ভাষায় যা ফাংশনটিকে প্রথম শ্রেণির মান হিসাবে বিবেচনা করে, বিশেষ কিছু ঘটে। আমি যদি এমন কিছু করি:
function foo(x)
return x
end
x = foo
পরিবর্তনশীলটি x
কেবল রেফারেন্সই function foo()
নয় তবে এটি উল্লেখ করে যে রাজ্যটি foo
শেষ সময় ফিরে এসেছিল। আসল যাদুটি তখন ঘটে যখন foo
অন্যান্য কার্যগুলি তার ক্ষেত্রের মধ্যে আরও সংজ্ঞায়িত করা হয়; এটি নিজস্ব মিনি-পরিবেশের মতো (ঠিক 'সাধারণভাবে' আমরা একটি বিশ্ব পরিবেশে ফাংশনগুলি সংজ্ঞায়িত করি)।
কার্যত এটি সি ++ (সি?) এর 'স্ট্যাটিক' কীওয়ার্ডের মতো একই সমস্যার অনেকগুলি সমাধান করতে পারে, যা একাধিক ফাংশন কলগুলিতে স্থানীয় ভেরিয়েবলের অবস্থা ধরে রাখে; তবে এটি আরও একই জাতীয় নীতির (স্থিতিশীল ভেরিয়েবল) কোনও ফাংশনে প্রয়োগ করার মতো, কারণ ফাংশনগুলি প্রথম শ্রেণির মান; ক্লোজারটি পুরো ফাংশনটির অবস্থা সংরক্ষণের জন্য সমর্থন যোগ করে (সি ++ এর স্থির ক্রিয়াকলাপগুলির সাথে কিছুই করার নয়)।
প্রথম শ্রেণীর মান হিসাবে ফাংশনগুলি চিকিত্সা এবং ক্লোজারগুলির জন্য সমর্থন যুক্ত করার অর্থ হ'ল মেমোরিতে একই ফাংশনের একাধিক উদাহরণ থাকতে পারে (ক্লাসগুলির অনুরূপ)। এর অর্থ হ'ল আপনি কোনও ফাংশনের অভ্যন্তরে সি ++ স্ট্যাটিক ভেরিয়েবলগুলির সাথে ডিল করার সময় প্রয়োজনীয় ফাংশনটির স্থিতি পুনরায় সেট না করে একই কোডটি পুনরায় ব্যবহার করতে পারেন (এটি সম্পর্কে ভুল হতে পারে?)।
লুয়ার ক্লোজার সাপোর্টের এখানে কিছু পরীক্ষা করা হচ্ছে।
--Closure testing
--By Trae Barlow
--
function myclosure()
print(pvalue)--nil
local pvalue = pvalue or 10
return function()
pvalue = pvalue + 10 --20, 31, 42, 53(53 never printed)
print(pvalue)
pvalue = pvalue + 1 --21, 32, 43(pvalue state saved through multiple calls)
return pvalue
end
end
x = myclosure() --x now references anonymous function inside myclosure()
x()--nil, 20
x() --21, 31
x() --32, 42
--43, 53 -- if we iterated x() again
ফলাফল:
nil
20
31
42
এটি জটিল হয়ে উঠতে পারে এবং এটি সম্ভবত ভাষা থেকে আলাদা হয়ে যায় তবে লুয়ায় মনে হয় যে যখনই কোনও ফাংশন সম্পাদন করা হয় তখন তার অবস্থা পুনরায় সেট করা হয়। আমি এটি বলছি কারণ উপরের কোড থেকে ফলাফলগুলি পৃথক হবে যদি আমরা myclosure
সরাসরি ফাংশন / রাজ্যে অ্যাক্সেস করে থাকি (বেনামে ফাংশনটি পরিবর্তনের পরিবর্তে) এটি pvalue
পুনরায় সেট করা হয় 10; তবে যদি আমরা এক্স (বেনামে ফাংশন) এর মাধ্যমে মাইক্লোজারের রাজ্যে অ্যাক্সেস করতে পারি তবে আপনি দেখতে পাচ্ছেন যে pvalue
এটি স্মরণে কোথাও বেঁচে আছে well আমার সন্দেহ হয় এর আরও কিছু আছে, সম্ভবত কেউ বাস্তবায়নের প্রকৃতি আরও ভালভাবে ব্যাখ্যা করতে পারে।
পিএস: আমি সি ++ 11 (আগের সংস্করণগুলির তুলনায় অন্য) কে চিনি না, সুতরাং লক্ষ করুন যে এটি সি ++ 11 এবং লুয়ার ক্লোজারগুলির মধ্যে তুলনা নয়। এছাড়াও, লুয়া থেকে সি ++ পর্যন্ত আঁকা সমস্ত 'লাইনগুলি স্থির ভেরিয়েবল এবং ক্লোজারগুলি 100% একই নয় বলে মিল; এমনকি যদি তারা কখনও কখনও একই সমস্যা সমাধানে ব্যবহৃত হয়।
আমি যে জিনিসটির বিষয়ে নিশ্চিত নই সেগুলি হ'ল উপরের কোড উদাহরণে বেনাম ফাংশন বা উচ্চতর ক্রম ফাংশনটি বন্ধ হিসাবে বিবেচনা করা হচ্ছে কিনা?
একটি বন্ধন একটি ফাংশন যা সম্পর্কিত রাষ্ট্র সম্পর্কিত:
পার্লে আপনি এর মতো ক্লোজার তৈরি করেন:
#!/usr/bin/perl
# This function creates a closure.
sub getHelloPrint
{
# Bind state for the function we are returning.
my ($first) = @_;a
# The function returned will have access to the variable $first
return sub { my ($second) = @_; print "$first $second\n"; };
}
my $hw = getHelloPrint("Hello");
my $gw = getHelloPrint("Goodby");
&$hw("World"); // Print Hello World
&$gw("World"); // PRint Goodby World
যদি আমরা সি ++ সরবরাহিত নতুন কার্যকারিতাটি দেখি।
এটি আপনাকে অবজেক্টের সাথে বর্তমান অবস্থা বাঁধতেও সহায়তা করে:
#include <string>
#include <iostream>
#include <functional>
std::function<void(std::string const&)> getLambda(std::string const& first)
{
// Here we bind `first` to the function
// The second parameter will be passed when we call the function
return [first](std::string const& second) -> void
{ std::cout << first << " " << second << "\n";
};
}
int main(int argc, char* argv[])
{
auto hw = getLambda("Hello");
auto gw = getLambda("GoodBye");
hw("World");
gw("World");
}
আসুন একটি সাধারণ ক্রিয়া বিবেচনা করুন:
function f1(x) {
// ... something
}
এই ফাংশনটিকে শীর্ষ স্তরের ফাংশন বলা হয় কারণ এটি অন্য কোনও ফাংশনের মধ্যে বাসা বাঁধে না। প্রতিটি জাভাস্ক্রিপ্ট ফাংশন নিজের সাথে "স্কোপ চেইন" নামে পরিচিত বস্তুর একটি তালিকা সংযুক্ত করে । এই স্কোপ চেইনটি বস্তুর একটি আদেশযুক্ত তালিকা। এই প্রতিটি বস্তু কিছু পরিবর্তনশীল সংজ্ঞায়িত করে।
শীর্ষ স্তরের ফাংশনগুলিতে স্কোপ চেইনে একটি একক বস্তু, বিশ্বব্যাপী অবজেক্ট থাকে। উদাহরণস্বরূপ, f1
উপরের ফাংশনটির স্কোপ চেইন রয়েছে যার মধ্যে একটি একক অবজেক্ট রয়েছে যা সমস্ত বিশ্বব্যাপী ভেরিয়েবলগুলি সংজ্ঞায়িত করে। (নোট করুন যে এখানে "অবজেক্ট" শব্দের অর্থ জাভাস্ক্রিপ্ট অবজেক্ট নয়, এটি কেবল একটি বাস্তবায়ন সংজ্ঞায়িত অবজেক্ট যা ভেরিয়েবল কনটেইনার হিসাবে কাজ করে, যেখানে জাভাস্ক্রিপ্টটি "চেহারাতে পারে" ভেরিয়েবলগুলি))
যখন এই ফাংশনটি চালু করা হয়, জাভাস্ক্রিপ্ট একটি "অ্যাক্টিভেশন অবজেক্ট" নামক কিছু তৈরি করে এবং স্কোপ চেইনের শীর্ষে রাখে। এই অবজেক্টে সমস্ত স্থানীয় ভেরিয়েবল রয়েছে (উদাহরণস্বরূপ x
এখানে)। সুতরাং এখন স্কোপ চেইনে আমাদের দুটি অবজেক্ট রয়েছে: প্রথমটি হল অ্যাক্টিভেশন অবজেক্ট এবং এর নীচে বিশ্বব্যাপী অবজেক্ট।
খুব সাবধানে লক্ষ করুন যে দুটি বিষয়গুলি বিভিন্ন সময়ে স্কোপ চেইনে রাখা হয়। ফাংশনটি সংজ্ঞায়িত হয়ে গেলে (যেমন, জাভাস্ক্রিপ্ট যখন ফাংশনটিকে বিশ্লেষণ করে ফাংশনটি তৈরি করে) গ্লোবাল অবজেক্ট স্থাপন করা হয় এবং ফাংশনটি চালিত হওয়ার সময় অ্যাক্টিভেশন অবজেক্ট প্রবেশ করে।
সুতরাং, আমরা এখন এটি জানি:
পরিস্থিতি আকর্ষণীয় হয়ে ওঠে যখন আমরা নেস্টেড ফাংশনগুলি নিয়ে কাজ করি। সুতরাং, আসুন এটি তৈরি করুন:
function f1(x) {
function f2(y) {
// ... something
}
}
f1
সংজ্ঞায়িত হয়ে গেলে আমরা কেবলমাত্র বৈশ্বিক অবজেক্টযুক্ত এর জন্য একটি স্কোপ চেইন পাই।
এখন যখন f1
ডাকা হয়, স্কোপ চেইনটি f1
অ্যাক্টিভেশন অবজেক্টটি পায়। এই অ্যাক্টিভেশন অবজেক্টে ভেরিয়েবল x
এবং ভেরিয়েবল রয়েছে f2
যা একটি ফাংশন। এবং, নোট যে f2
সংজ্ঞায়িত হচ্ছে। সুতরাং, এই সময়ে, জাভাস্ক্রিপ্ট এছাড়াও জন্য একটি নতুন স্কোপ চেইন সংরক্ষণ করে f2
। এই অভ্যন্তরীণ ফাংশনটির জন্য স্কোপ চেইন সংরক্ষণ করা বর্তমান স্কোপ চেইন কার্যকর। বর্তমান স্কোপ চেইন কার্যকর হয় f1
s অত: পর f2
'র সুযোগ চেইন হয় f1
s' এর বর্তমান যার অ্যাক্টিভেশন বস্তুর মধ্যে রয়েছে - সুযোগ শৃঙ্খল f1
ও বৈশ্বিক অবজেক্ট।
যখন f2
ডাকা হয়, এটি তার নিজস্ব অ্যাক্টিভেশন অবজেক্টটি ধারণ করে y
, এর স্কোপ চেইনে যুক্ত হয় যা ইতিমধ্যে অ্যাক্টিভেশন অবজেক্ট f1
এবং গ্লোবাল অবজেক্ট ধারণ করে ।
যদি এর মধ্যে অন্য কোনও নেস্টেড ফাংশন সংজ্ঞায়িত করা হয় তবে f2
এর স্কোপ চেইনে সংজ্ঞা সময়ে তিনটি অবজেক্ট (দুটি বহিরাগত ক্রিয়াকলাপগুলির 2 টি অ্যাক্টিভেশন অবজেক্ট এবং বৈশ্বিক বস্তু) থাকবে এবং অনুরোধের সময় 4 থাকবে।
সুতরাং, এখন আমরা বুঝতে পারি যে স্কোপ চেইন কীভাবে কাজ করে তবে আমরা এখনও বন্ধ হওয়ার বিষয়ে কথা বলিনি।
একটি ফাংশন অবজেক্ট এবং স্কোপ (ভেরিয়েবল বাইন্ডিংগুলির একটি সেট) এর সংমিশ্রণ যেখানে ফাংশনের ভেরিয়েবলগুলি সমাধান করা হয় তাকে কম্পিউটার বিজ্ঞান সাহিত্যের একটি ক্লোজার বলা হয় - জাভাস্ক্রিপ্ট ডেভিড ফ্লানাগনের চূড়ান্ত গাইড
বেশিরভাগ ফাংশন একই স্কোপ চেইনটি ব্যবহার করে ডেকে আনা হয় যা কার্যটি সংজ্ঞায়িত হওয়ার সময় কার্যকর ছিল এবং এটি কোনও ব্যাপারেই জড়িত না যে এতে কোনও জড়িত রয়েছে। বন্ধগুলি আকর্ষণীয় হয়ে ওঠে যখন সেগুলি সংজ্ঞায়িত করার সময় কার্যকর ছিল এমনটির চেয়ে আলাদা স্কোপ চেইনের অধীনে ডাকা হয়। এটি সবচেয়ে সাধারণভাবে ঘটে যখন কোনও নেস্টেড ফাংশন অবজেক্টটি তার সংজ্ঞায়িত ফাংশন থেকে ফিরে আসে।
যখন ফাংশনটি ফিরে আসে, তখন সেই অ্যাক্টিভেশন অবজেক্টটি স্কোপ চেইন থেকে সরানো হয়। যদি কোনও নেস্টেড ফাংশন না থাকে তবে অ্যাক্টিভেশন অবজেক্টের কোনও উল্লেখ নেই এবং এটি আবর্জনা সংগ্রহ করে collected যদি নেস্টেড ফাংশনগুলি সংজ্ঞায়িত করা হয়, তবে সেই ফাংশনের প্রত্যেকটির স্কোপ চেইনের একটি রেফারেন্স রয়েছে এবং স্কোপ চেইনটি অ্যাক্টিভেশন অবজেক্টকে বোঝায়।
যদি those নেস্টেড ফাংশনগুলির অবজেক্টগুলি তাদের বাহ্যিক ক্রিয়াকলাপের মধ্যে থেকে যায় তবে তবে তারা নিজেরাই তাদের উল্লেখ করা অ্যাক্টিভেশন অবজেক্টের সাথে আবর্জনা সংগ্রহ করবে। তবে যদি ফাংশনটি কোনও নেস্টেড ফাংশনটি সংজ্ঞায়িত করে এবং এটি ফিরিয়ে দেয় বা কোথাও একটি সম্পত্তিতে সঞ্চয় করে, তবে নেস্টেড ফাংশনটির একটি বাহ্যিক উল্লেখ থাকবে। এটি আবর্জনা সংগ্রহ করা হবে না এবং এটি সক্রিয়করণ অবজেক্টটি যা আবর্জনা সংগ্রহ করে তা সংগ্রহ করা হবে না।
আমাদের উপরের উদাহরণে, আমরা এ f2
থেকে ফিরে f1
আসি না , অতএব, যখন কোনও কল f1
ফিরে আসে, তখন তার সক্রিয়করণ অবজেক্টটি তার স্কোপ চেইন এবং সংগ্রহ করা আবর্জনা থেকে সরানো হবে। তবে আমাদের যদি এরকম কিছু থাকে:
function f1(x) {
function f2(y) {
// ... something
}
return f2;
}
এখানে, ফিরে আসার f2
জন্য একটি স্কোপ চেইন থাকবে যার সক্রিয়করণ অবজেক্ট f1
থাকবে এবং তাই এটি আবর্জনা সংগ্রহ করা হবে না। এই মুহুর্তে, আমরা যদি কল করি তবে এটি বাইরে না থাকলেও f2
এটির f1
ভেরিয়েবল অ্যাক্সেস করতে সক্ষম হবে ।x
f1
সুতরাং আমরা দেখতে পাচ্ছি যে একটি ফাংশন এটির সাথে স্কোপ চেইন রাখে এবং স্কোপ চেইনের সাথে বাইরের ফাংশনের সমস্ত সক্রিয়করণ অবজেক্ট আসে। এটি বন্ধের সারাংশ। আমরা বলি যে জাভাস্ক্রিপ্টে ফাংশনগুলি "বর্ণিতভাবে স্কোপযুক্ত" , যার অর্থ তারা যখন ডাকা হয়েছিল তখন সক্রিয় ছিল এমন সুযোগের বিপরীত হিসাবে সংজ্ঞায়িত হওয়ার পরে তারা সক্রিয় ছিল এমন সুযোগটি সংরক্ষণ করে।
এমন অনেকগুলি শক্তিশালী প্রোগ্রামিং কৌশল রয়েছে যাতে প্রাইভেট ভেরিয়েবল, ইভেন্ট চালিত প্রোগ্রামিং, আংশিক প্রয়োগ ইত্যাদির মতো ক্লোজার জড়িত থাকে
এছাড়াও মনে রাখবেন যে এই সমস্তগুলি সেই সমস্ত ভাষার ক্ষেত্রে প্রযোজ্য যা ক্লোজার সমর্থন করে। উদাহরণস্বরূপ পিএইচপি (5.3+), পাইথন, রুবি ইত্যাদি
একটি বন্ধ হ'ল একটি সংকলক অপ্টিমাইজেশন (ওরফে সিনট্যাকটিক চিনি?)। কিছু লোক এটিকে দরিদ্র মানুষের উদ্দেশ্য হিসাবেও উল্লেখ করেছেন।
এরিক লিপার্টের উত্তর দেখুন : (নীচে অংশ)
সংকলক এই জাতীয় কোড উত্পন্ন করবে:
private class Locals
{
public int count;
public void Anonymous()
{
this.count++;
}
}
public Action Counter()
{
Locals locals = new Locals();
locals.count = 0;
Action counter = new Action(locals.Anonymous);
return counter;
}
ধারণা তৈরী কর?
এছাড়াও, আপনি তুলনা চেয়েছিলেন। ভিবি এবং জেএসক্রিপ্ট উভয়ই একই উপায়ে ক্লোজার তৈরি করে।