জাভাস্ক্রিপ্ট ক্লোজার বনাম বেনামে ফাংশন


562

আমার এবং আমার এক বন্ধু বর্তমানে জেএসে বন্ধ কী কী এবং কী নয় তা নিয়ে আলোচনা করছি। আমরা কেবল এটি নিশ্চিত করতে চাই যে আমরা সত্যই এটি সঠিকভাবে বুঝতে পেরেছি।

এই উদাহরণটি নেওয়া যাক। আমাদের একটি গণনা লুপ রয়েছে এবং বিলম্বিত কনসোলে কাউন্ট ভেরিয়েবল মুদ্রণ করতে চাই। অতএব আমরা কাউন্টার ভেরিয়েবলের মান ক্যাপচারের জন্য ব্যবহার করি setTimeoutএবং ক্লোজারগুলি নিশ্চিত হয়ে যায় যে এটি N এর চেয়ে N বার প্রিন্ট করবে না make

ছাড়া ভুল সমাধান বন্ধ বা কাছাকাছি কিছু বন্ধ হবে:

for(var i = 0; i < 10; i++) {
    setTimeout(function() {
        console.log(i);
    }, 1000);
}

যা অবশ্যই iলুপের পরে 10 গুণ মান প্রিন্ট করবে 10

সুতরাং তার চেষ্টা ছিল:

for(var i = 0; i < 10; i++) {
    (function(){
        var i2 = i;
        setTimeout(function(){
            console.log(i2);
        }, 1000)
    })();
}

প্রত্যাশিত 0 থেকে 9 মুদ্রণ।

আমি তাকে বলেছিলাম যে তিনি ক্যাপচারের জন্য ক্লোজার ব্যবহার করছেন না i, তবে তিনি জোর দিয়ে বলেছেন যে তিনি আছেন। আমি প্রমাণ করেছি যে সে লুপ বডি অন্যটির মধ্যে রেখে (ক্লোজারগুলিকে তার বেনামে ফাংশনটি দিয়ে ) আবার 10 বার প্রিন্ট করে ক্লোজার ব্যবহার করে না । একই প্রযোজ্য যদি আমি একটি তার ফাংশন সংরক্ষণ এবং এটি চালানো পর লুপ, এছাড়াও 10 বার 10. মুদ্রণ তাই আমার যুক্তি যে তিনি সত্যিই নেই ক্যাপচার মান , তার সংস্করণ উপার্জন না একটি বন্ধ।setTimeoutsetTimeoutvari

আমার চেষ্টা ছিল:

for(var i = 0; i < 10; i++) {
    setTimeout((function(i2){
        return function() {
            console.log(i2);
        }
    })(i), 1000);
}

সুতরাং আমি ক্যাপচার i( i2বন্ধের মধ্যে নাম দেওয়া ), কিন্তু এখন আমি অন্য একটি ফাংশন ফিরে এসে এটিকে পাশ কাটিয়েছি। আমার ক্ষেত্রে, ফাংশনটি সেটটাইমআউটে সত্যই ক্যাপচারে চলে গেছে i

এখন ক্লোজারগুলি কে ব্যবহার করছে এবং কে না?

নোট করুন যে উভয় সমাধান কনসোলে দেরি করে 0 থেকে 9 মুদ্রণ করে, তাই তারা আসল সমস্যাটি সমাধান করে, তবে আমরা বুঝতে চাই যে এই দুটি সমাধানগুলির মধ্যে কোনটি সমাপনে ক্লোজার ব্যবহার করে



1
@ লেলিজ: দ্বিতীয় লিঙ্কের জন্য আমার নিনজা সম্পাদনা দেখুন।
ব্লেন্ডার

2
আমরা সবেমাত্র একটি চুক্তি করেছি: যিনি সঠিক তিনি এই প্রশ্নের সাথে সম্পর্কিত এসও পয়েন্টগুলি পেতে
চলেছেন

1
@ লেলিম - আপনি উভয় ক্লোজার ব্যবহার করছেন। আপনার দু'জনেই দুটি ফাংশন করেছেন - একটি বাহ্যিক ফাংশন এবং একটি অভ্যন্তরীণ ফাংশন; এবং আপনার উভয় অভ্যন্তরীণ ফাংশন ক্লোজার। আপনার সমস্ত ফাংশন ল্যাম্বডাস ( বেনামে ফাংশন )। বিস্তারিত জানার জন্য আমার উত্তর পড়ুন।
অদিত এম শাহ

1
@blesh - পরিবর্তিত বন্ধটি কী তা আমার কোনও ধারণা নেই। আমি দেখতে পাচ্ছি যে আপনার লিঙ্কটি সি # কোডের দিকে নির্দেশ করছে। জাভাস্ক্রিপ্ট দ্বারা সংশোধিত ক্লোজারগুলি সমর্থিত?
অদিত এম শাহ

উত্তর:


649

সম্পাদকের দ্রষ্টব্য: জাভাস্ক্রিপ্টের সমস্ত ফাংশন এই পোস্টে বর্ণিত হিসাবে ক্লোজার । তবে আমরা কেবলমাত্র এই ফাংশনগুলির একটি উপসেট সনাক্ত করতে আগ্রহী যা একটি তাত্ত্বিক দৃষ্টিকোণ থেকে আকর্ষণীয় । অতএব বন্ধ শব্দ শব্দের কোনও রেফারেন্স অন্যথায় না বলা না থাকলে কার্যের এই উপসেটটিকে উল্লেখ করবে।

সমাপনের জন্য একটি সহজ ব্যাখ্যা:

  1. একটি ফাংশন নিন। একে এফ বলি Let's
  2. এফ এর সমস্ত ভেরিয়েবল তালিকাভুক্ত করুন
  3. ভেরিয়েবল দুটি ধরণের হতে পারে:
    1. স্থানীয় ভেরিয়েবল (আবদ্ধ ভেরিয়েবল)
    2. অ-স্থানীয় ভেরিয়েবল (বিনামূল্যে ভেরিয়েবল)
  4. যদি এফের কোনও মুক্ত ভেরিয়েবল থাকে না তবে এটি বন্ধ হতে পারে না।
  5. এফ কোন বিনামূল্যে ভেরিয়েবল (যেখানে সংজ্ঞায়িত করা হয় থাকে একটি এফ অভিভাবক সুযোগ) তারপর:
    1. এফ এর কেবলমাত্র একটি প্যারেন্ট স্কোপ থাকতে হবে যেখানে একটি ফ্রি ভেরিয়েবল বাধ্য।
    2. এফ হয়, তাহলে রেফারেন্সড বাইরে থেকে যে পিতা বা মাতা সুযোগ, তারপর এটির জন্য একটি অবসান হয়ে যে বিনামূল্যে পরিবর্তনশীল।
    3. এই মুক্ত পরিবর্তনশীলটিকে এফ বন্ধের একটি মূল্যায়ন বলা হয়।

কারা বন্ধ ব্যবহার করে এবং কারা ব্যবহার করে না তা নির্ধারণ করার জন্য এখন এটি ব্যবহার করা যাক (ব্যাখ্যাগুলির জন্য আমি ফাংশনগুলির নাম দিয়েছি):

কেস 1: আপনার বন্ধুর প্রোগ্রাম

for (var i = 0; i < 10; i++) {
    (function f() {
        var i2 = i;
        setTimeout(function g() {
            console.log(i2);
        }, 1000);
    })();
}

উপরের প্রোগ্রামে দুটি ফাংশন রয়েছে: fএবং g। আসুন দেখুন তারা বন্ধ হয় কিনা:

এর জন্য f:

  1. ভেরিয়েবলগুলি তালিকাবদ্ধ করুন:
    1. i2একটি স্থানীয় পরিবর্তনশীল।
    2. iএকটি বিনামূল্যে পরিবর্তনশীল।
    3. setTimeoutএকটি বিনামূল্যে পরিবর্তনশীল।
    4. gএকটি স্থানীয় পরিবর্তনশীল।
    5. consoleএকটি বিনামূল্যে পরিবর্তনশীল।
  2. প্রতিটি বিনামূল্যে ভেরিয়েবল আবদ্ধ যার মূল স্কোপটি সন্ধান করুন:
    1. iহয় আবদ্ধ সার্বিক ব্যাপ্তি।
    2. setTimeoutহয় আবদ্ধ সার্বিক ব্যাপ্তি।
    3. consoleহয় আবদ্ধ সার্বিক ব্যাপ্তি।
  3. কোন ক্ষেত্রটিতে ফাংশনটি উল্লেখ করা হয় ? বিশ্বব্যাপী সুযোগ
    1. অতএব দ্বারা বন্ধi হয় না ।f
    2. অতএব দ্বারা বন্ধsetTimeout হয় না ।f
    3. অতএব দ্বারা বন্ধconsole হয় না ।f

সুতরাং ফাংশন fএকটি বন্ধ নয়।

এর জন্য g:

  1. ভেরিয়েবলগুলি তালিকাবদ্ধ করুন:
    1. consoleএকটি বিনামূল্যে পরিবর্তনশীল।
    2. i2একটি বিনামূল্যে পরিবর্তনশীল।
  2. প্রতিটি বিনামূল্যে ভেরিয়েবল আবদ্ধ যার মূল স্কোপটি সন্ধান করুন:
    1. consoleহয় আবদ্ধ সার্বিক ব্যাপ্তি।
    2. i2হয় আবদ্ধ পরিধি থেকে f
  3. কোন ক্ষেত্রটিতে ফাংশনটি উল্লেখ করা হয় ? এর সুযোগsetTimeout
    1. অতএব দ্বারা বন্ধconsole হয় না ।g
    2. সুতরাং i2দ্বারা বন্ধ হয় g

সুতরাং ফাংশনটি gফ্রি ভেরিয়েবলের i2(যা একটি মূল্যায়ন জন্য g) এটি যখন অভ্যন্তরীণ থেকে রেফারেন্স হয় তখন বন্ধ হয়ে যায় setTimeout

আপনার পক্ষে খারাপ: আপনার বন্ধুটি বন্ধ ব্যবহার করছে। অভ্যন্তরীণ ফাংশন একটি বন্ধ।

কেস ২: আপনার প্রোগ্রাম

for (var i = 0; i < 10; i++) {
    setTimeout((function f(i2) {
        return function g() {
            console.log(i2);
        };
    })(i), 1000);
}

উপরের প্রোগ্রামে দুটি ফাংশন রয়েছে: fএবং g। আসুন দেখুন তারা বন্ধ হয় কিনা:

এর জন্য f:

  1. ভেরিয়েবলগুলি তালিকাবদ্ধ করুন:
    1. i2একটি স্থানীয় পরিবর্তনশীল।
    2. gএকটি স্থানীয় পরিবর্তনশীল।
    3. consoleএকটি বিনামূল্যে পরিবর্তনশীল।
  2. প্রতিটি বিনামূল্যে ভেরিয়েবল আবদ্ধ যার মূল স্কোপটি সন্ধান করুন:
    1. consoleহয় আবদ্ধ সার্বিক ব্যাপ্তি।
  3. কোন ক্ষেত্রটিতে ফাংশনটি উল্লেখ করা হয় ? বিশ্বব্যাপী সুযোগ
    1. অতএব দ্বারা বন্ধconsole হয় না ।f

সুতরাং ফাংশন fএকটি বন্ধ নয়।

এর জন্য g:

  1. ভেরিয়েবলগুলি তালিকাবদ্ধ করুন:
    1. consoleএকটি বিনামূল্যে পরিবর্তনশীল।
    2. i2একটি বিনামূল্যে পরিবর্তনশীল।
  2. প্রতিটি বিনামূল্যে ভেরিয়েবল আবদ্ধ যার মূল স্কোপটি সন্ধান করুন:
    1. consoleহয় আবদ্ধ সার্বিক ব্যাপ্তি।
    2. i2হয় আবদ্ধ পরিধি থেকে f
  3. কোন ক্ষেত্রটিতে ফাংশনটি উল্লেখ করা হয় ? এর সুযোগsetTimeout
    1. অতএব দ্বারা বন্ধconsole হয় না ।g
    2. সুতরাং i2দ্বারা বন্ধ হয় g

সুতরাং ফাংশনটি gফ্রি ভেরিয়েবলের i2(যা একটি মূল্যায়ন জন্য g) এটি যখন অভ্যন্তরীণ থেকে রেফারেন্স হয় তখন বন্ধ হয়ে যায় setTimeout

আপনার পক্ষে ভাল: আপনি বন্ধ ব্যবহার করছেন। অভ্যন্তরীণ ফাংশন একটি বন্ধ।

সুতরাং আপনি এবং আপনার বন্ধু উভয়ই ক্লোজার ব্যবহার করছেন। তর্ক বন্ধ কর. আমি আশা করি বন্ধের ধারণাটি এবং আপনার উভয়ের জন্য কীভাবে সেগুলি সনাক্ত করব তা আমি সাফ করে দিয়েছি

সম্পাদনা করুন: সমস্ত ফাংশন ক্লোজার (ক্রেডিট @ পিটার) কেন তা সম্পর্কে একটি সহজ ব্যাখ্যা:

প্রথমে নিম্নলিখিত প্রোগ্রামটি বিবেচনা করুন (এটি নিয়ন্ত্রণ ):

lexicalScope();

function lexicalScope() {
    var message = "This is the control. You should be able to see this message being alerted.";

    regularFunction();

    function regularFunction() {
        alert(eval("message"));
    }
}

  1. আমরা জানি যে উভয়ই lexicalScopeএবং উপরের সংজ্ঞাটিregularFunction বন্ধ নয় ।
  2. যখন আমরা প্রোগ্রামটি কার্যকর করি তখন আমরা সতর্কতা প্রত্যাশা করি কারণ এটি কোনও বন্ধ নয় (যেমন এটির এর প্যারেন্ট স্কোপের সমস্ত ভেরিয়েবলের অ্যাক্সেস রয়েছে - সহ )।message regularFunctionmessage
  3. যখন আমরা প্রোগ্রামটি কার্যকর করি তখন আমরা লক্ষ্য করি যে messageএটি অবশ্যই সতর্ক হয়ে গেছে।

পরবর্তী আসুন নীচের প্রোগ্রামটি বিবেচনা করুন (এটি বিকল্প ):

var closureFunction = lexicalScope();

closureFunction();

function lexicalScope() {
    var message = "This is the alternative. If you see this message being alerted then in means that every function in JavaScript is a closure.";

    return function closureFunction() {
        alert(eval("message"));
    };
}

  1. আমরা জানি যে কেবলমাত্র উপরের সংজ্ঞাটি থেকেclosureFunction বন্ধ করা ।
  2. আমরা যখন প্রোগ্রাম চালানো আমরা আশা message সতর্ক করা না কারণ closureFunction (অর্থাত এটি শুধুমাত্র তার সমস্ত অ্যাক্সেস আছে একটি অবসান হয় অ-স্থানীয় ভেরিয়েবলসময় ফাংশন তৈরি করা হয় ( এই উত্তরটি দেখুন - এই অন্তর্ভুক্ত নয়) message)।
  3. আমরা যখন প্রোগ্রামটি সম্পাদন করি আমরা পর্যবেক্ষণ করি messageযা আসলে সতর্ক করা হচ্ছে।

এ থেকে আমরা কী অনুমান করি?

  1. জাভাস্ক্রিপ্ট অনুবাদকারীরা অন্য ফাংশনগুলির সাথে যেভাবে আচরণ করে তার থেকে ক্লোজারগুলিকে আলাদাভাবে আচরণ করে না।
  2. প্রতিটি ফাংশন তার স্কোপ চেইনটি বয়ে নিয়ে যায়। বন্ধগুলিতে পৃথক রেফারেন্সিং পরিবেশ নেই।
  3. একটি ক্লোজার হ'ল অন্যান্য ফাংশনের মতো। আমরা শুধু কল তাদের বন্ধ যখন তারা হয় রেফারেন্সড একটি সুযোগ বাহিরে সুযোগ যা তারা অন্তর্গত কারণ এই একটি আকর্ষণীয় ক্ষেত্রে দেখা যায়।

40
গ্রহণযোগ্য কারণ আপনি বিশদে খুব বেশি যান, খুব সুন্দর যা হচ্ছে তা ব্যাখ্যা করে। এবং অবশেষে, আমি এখন আরও বুঝতে পেরেছি যে বন্ধ কী, বা আরও ভালভাবে বলা হয়েছে: জেএসে কীভাবে ভেরিয়েবল বন্ডিং কাজ করে।
লীমস

3
কেস 1, আপনি বলে যে gসুযোগ রানে setTimeout, কিন্তু কেস 2 আপনি বলে যে fবিশ্বব্যাপী সুযোগ রান। তারা উভয়ই সেটটাইমআউটের মধ্যে রয়েছে, তবে পার্থক্য কী?
rosscj2533

9
আপনি কি এই জন্য আপনার উত্স বিবরণ করবেন? আমি কখনই এমন সংজ্ঞা দেখিনি যে যেখানে কোনও সুযোগে বলা হয় তবে অন্য জায়গায় নয় তবে কোনও ফাংশন বন্ধ হতে পারে। সুতরাং, এই সংজ্ঞাটি আরও সাধারণ সংজ্ঞার একটি উপসেটের মতো বলে মনে হচ্ছে ( কেভের উত্তর দেখুন ) যেখানে একটি বন্ধ হ'ল একটি ক্লোজার হ'ল এটির স্কোপটি নির্বিশেষে বন্ধ করা হয়, বা এটি কখনও না বলা হলেও!
ব্রিগ্যুই 37

11
@ অদিতএমশাহ একটি বন্ধন কী তা সম্পর্কে আমি আপনার সাথে একমত, তবে আপনি জাভাস্ক্রিপ্টে নিয়মিত ফাংশন এবং ক্লোজারের মধ্যে পার্থক্য রয়েছে বলে কথা বলছেন । এখানে কোন পার্থক্য নেই; অভ্যন্তরীণভাবে প্রতিটি ফাংশন এটির সাথে নির্দিষ্ট স্কোপ চেইনের একটি রেফারেন্স বহন করে। জেএস ইঞ্জিন এটিকে আলাদা মামলা বলে মনে করে না। জটিল চেক-লিস্টের প্রয়োজন নেই; কেবলমাত্র জেনে থাকুন যে প্রতিটি ফাংশন অবজেক্ট লেবেসিক স্কোপ বহন করে। ভেরিয়েবল / বৈশিষ্ট্যগুলি বিশ্বব্যাপী উপলভ্য হওয়ার কারণে ফাংশনটি কোনও কম বন্ধ হয় না (এটি কেবল একটি অকেজো ক্ষেত্রে)।
পিটার

13
@ পিটার - আপনি কি জানেন, আপনি সঠিক। নিয়মিত ফাংশন এবং বন্ধের মধ্যে কোনও পার্থক্য নেই। আমি এটি প্রমাণ করার জন্য একটি পরীক্ষা চালিয়েছি এবং এটি আপনার পক্ষে ফলাফল: এখানে নিয়ন্ত্রণ এবং এখানে বিকল্প । আপনি যা বলছেন তা বোধগম্য। জাভাস্ক্রিপ্ট দোভাষীর বন্ধের জন্য বিশেষ বুককিপিং করা দরকার। এগুলি কেবল প্রথম শ্রেণীর ফাংশন সহ একটি বর্ণিত স্কোপযুক্ত ভাষার বাই-পণ্য। আমার জ্ঞান আমি যা পড়ি তার মধ্যে সীমাবদ্ধ ছিল (যা মিথ্যা ছিল)। আমাকে সংশোধন করার জন্য আপনাকে ধন্যবাদ। আমি আমার উত্তর একই প্রতিফলিত আপডেট করব।
অদিত এম শাহ

96

closureসংজ্ঞা অনুযায়ী :

"ক্লোজার" হ'ল একটি অভিব্যক্তি (সাধারণত একটি ফাংশন) যার সাথে এমন পরিবেশের সাথে মুক্ত ভেরিয়েবল থাকতে পারে যা সেই ভেরিয়েবলগুলি আবদ্ধ করে (যা "বন্ধ করে দেয়" এক্সপ্রেশনটি)।

আপনি closureযদি কোনও ফাংশন সংজ্ঞায়িত করেন যা কোনও ভেরিয়েবল ব্যবহার করে যা ফাংশনের বাইরে সংজ্ঞায়িত হয়। (আমরা ভেরিয়েবলটিকে একটি ফ্রি ভেরিয়েবল বলি )।
এগুলি সমস্ত ব্যবহার করে closure(এমনকি প্রথম উদাহরণেও)।


1
তৃতীয় সংস্করণটি কীভাবে ফাংশনের বাইরে সংজ্ঞায়িত একটি চলক ব্যবহার করে?
জন

1
@ জন ফিরিয়ে ফাংশন ব্যবহার i2যা বাইরে সংজ্ঞায়িত করা হয়েছে।
কেভ

1
@ কেভ আপনি যদি ফাংশনটির বাইরে সংজ্ঞায়িত একটি ভেরিয়েবল ব্যবহার করে এমন কোনও ফাংশন সংজ্ঞায়িত করেন তবে আপনি ক্লোজার ব্যবহার করছেন ...... তারপরে "কেস 1:" আদিতে এম শাহ "এর আপনার বন্ধুর প্রোগ্রাম" এর উত্তর "ফাংশন এফ" একটি বন্ধ? এটি আই ব্যবহার করে (ভেরিয়েবল যা ফাংশনের বাইরে সংজ্ঞায়িত করা হয়)। গ্লোবাল স্কোপ একটি নির্ধারক রেফারেন্স না?
ইন্টার্নাল-


54

সংক্ষেপে জাভাস্ক্রিপ্ট বন্ধকরণ একটি ফাংশনকে একটি পরিবর্তনশীল অ্যাক্সেসের অনুমতি দেয় যা একটি লেজিক্যাল-প্যারেন্ট ফাংশনে ঘোষণা করা হয়

আসুন আরও বিস্তারিত ব্যাখ্যা দেখুন। ক্লোজারগুলি বুঝতে জাভাস্ক্রিপ্ট স্কোপগুলি কীভাবে ভেরিয়েবল হয় তা বোঝা গুরুত্বপূর্ণ।

সুযোগগুলি

জাভাস্ক্রিপ্টে স্কোপগুলি ফাংশন দিয়ে সংজ্ঞায়িত করা হয়। প্রতিটি ফাংশন একটি নতুন সুযোগকে সংজ্ঞায়িত করে।

নিম্নলিখিত উদাহরণ বিবেচনা করুন;

function f()
{//begin of scope f
  var foo='hello'; //foo is declared in scope f
  for(var i=0;i<2;i++){//i is declared in scope f
     //the for loop is not a function, therefore we are still in scope f
     var bar = 'Am I accessible?';//bar is declared in scope f
     console.log(foo);
  }
  console.log(i);
  console.log(bar);
}//end of scope f

কলিং এফ প্রিন্টস

hello
hello
2
Am I Accessible?

আসুন এখন বিবেচনা করা যাক আমরা gঅন্য ফাংশন মধ্যে সংজ্ঞায়িত একটি ফাংশন আছে f

function f()
{//begin of scope f
  function g()
  {//being of scope g
    /*...*/
  }//end of scope g
  /*...*/
}//end of scope f

আমরা ডাকব আভিধানিক পিতা বা মাতা এর । যেমনটি এখন আমাদের 2 টি স্কোপ রয়েছে তার আগে ব্যাখ্যা করা হয়েছে; সুযোগ এবং সুযোগ ।fgfg

তবে একটি সুযোগ অন্য ক্ষেত্রের মধ্যে "ভিতরে" তাই বাচ্চা ফাংশনটির সুযোগটি পিতামাতার ফাংশনের সুযোগের অংশ? প্যারেন্ট ফাংশনের সুযোগে ঘোষিত ভেরিয়েবলগুলির সাথে কী ঘটে; আমি কি শিশু ফাংশনের সুযোগ থেকে তাদের অ্যাক্সেস করতে সক্ষম হব? ঠিক সেখানেই ক্লোজারগুলি এগিয়ে যায়।

বন্ধ

জাভাস্ক্রিপ্টে ফাংশনটি gস্কোপটিতে ঘোষিত কোনও ভেরিয়েবল অ্যাক্সেস করতে পারে না gতবে প্যারেন্ট ফাংশনের সুযোগে ঘোষিত কোনও ভেরিয়েবল অ্যাক্সেস করতে পারে f

নিম্নলিখিত বিবেচনা করুন;

function f()//lexical parent function
{//begin of scope f
  var foo='hello'; //foo declared in scope f
  function g()
  {//being of scope g
    var bar='bla'; //bar declared in scope g
    console.log(foo);
  }//end of scope g
  g();
  console.log(bar);
}//end of scope f

কলিং এফ প্রিন্টস

hello
undefined

লাইনটি তাকান console.log(foo);। এই মুহুর্তে আমরা সুযোগে রয়েছি gএবং আমরা সুযোগ fooহিসাবে ঘোষিত ভেরিয়েবলটি অ্যাক্সেস করার চেষ্টা করি f। তবে যেমনটি বলা হয়েছে যে আমরা এখানে একটি লেজিক্যাল প্যারেন্ট ফাংশনে ঘোষিত কোনও পরিবর্তনশীল অ্যাক্সেস করতে পারি; gএর লেজিক্যাল পিতা-মাতা f। সুতরাং helloমুদ্রিত হয়।
আসুন এখন লাইনটি দেখুন console.log(bar);। এই মুহুর্তে আমরা সুযোগে রয়েছি fএবং আমরা সুযোগ barহিসাবে ঘোষিত ভেরিয়েবলটি অ্যাক্সেস করার চেষ্টা করি gbarবর্তমান সুযোগে ঘোষিত হয় না এবং ফাংশনটি gএর পিতামাতার নয় f, তাই barঅপরিজ্ঞাত

আসলে আমরা একটি লেজিকাল "গ্র্যান্ড প্যারেন্ট" ফাংশনের সুযোগ হিসাবে ঘোষিত ভেরিয়েবলগুলিও অ্যাক্সেস করতে পারি। সুতরাং যদি ফাংশন hমধ্যে নির্ধারিত একটি ফাংশন আছেg

function f()
{//begin of scope f
  function g()
  {//being of scope g
    function h()
    {//being of scope h
      /*...*/
    }//end of scope h
    /*...*/
  }//end of scope g
  /*...*/
}//end of scope f

তারপর hসব ভেরিয়েবল ফাংশনের সুযোগ ঘোষণা অ্যাক্সেস করতে সক্ষম হবে h, gএবং f। এটি ক্লোজার দিয়ে করা হয় । জাভাস্ক্রিপ্টের ক্লোজারগুলিতে আমাদের লেক্সিকাল প্যারেন্ট ফাংশন, লেজিকাল গ্র্যান্ড প্যারেন্ট ফাংশন, লেক্সিকাল গ্র্যান্ড-গ্র্যান্ড প্যারেন্ট ফাংশন ইত্যাদিতে ঘোষিত যে কোনও চলক অ্যাক্সেসের অনুমতি দেয় ; এটিকে স্কোপ চেইন হিসাবে দেখা যায় ; scope of current function -> scope of lexical parent function -> scope of lexical grand parent function -> ... কোনও লাসিক্যাল প্যারেন্ট নেই এমন শেষ প্যারেন্ট ফাংশন পর্যন্ত।

উইন্ডো অবজেক্ট

আসলে চেইনটি শেষ পিতামাতার কার্যক্রমে থামে না। আরও একটি বিশেষ সুযোগ আছে; বিশ্বব্যাপী সুযোগ । কোনও কার্যক্রমে ঘোষিত না হওয়া প্রতিটি পরিবর্তনশীলকে বিশ্বব্যাপী ঘোষিত হিসাবে ঘোষণা করা হয়। বৈশ্বিক ক্ষেত্রের দুটি বিশেষত্ব রয়েছে;

  • গ্লোবাল স্কোপে ঘোষিত প্রতিটি পরিবর্তনশীল সর্বত্রই অ্যাক্সেসযোগ্য
  • বৈশ্বিক স্কোপে ঘোষিত ভেরিয়েবলগুলি windowবস্তুর বৈশিষ্ট্যের সাথে সামঞ্জস্য করে ।

সুতরাং fooবৈশ্বিক পরিমণ্ডলে পরিবর্তনশীল ঘোষণার ঠিক দুটি উপায় রয়েছে ; হয় কোনও ফাংশনে এটি ঘোষণা না করে বা fooউইন্ডো অবজেক্টের সম্পত্তি সেট করে ।

উভয় প্রচেষ্টা ক্লোজার ব্যবহার করে uses

এখন আপনি আরও বিস্তারিত ব্যাখ্যা পড়েছেন এটি এখন স্পষ্ট হতে পারে যে উভয় সমাধানই ক্লোজার ব্যবহার করে। তবে নিশ্চিত হওয়ার জন্য, আসুন একটি প্রমাণ দিন।

আসুন একটি নতুন প্রোগ্রামিং ভাষা তৈরি করি; জাভাস্ক্রিপ্ট-কোন-বন্ধ। নামটি যেমন বোঝায়, জাভাস্ক্রিপ্ট-নো-ক্লোজার জাভাস্ক্রিপ্টের সমান এটি বাদে এটি ক্লোজারগুলিকে সমর্থন করে না।

অন্য কথায়;

var foo = 'hello';
function f(){console.log(foo)};
f();
//JavaScript-No-Closure prints undefined
//JavaSript prints hello

ঠিক আছে, আসুন দেখুন জাভাস্ক্রিপ্ট-নো-ক্লোজারের সাথে প্রথম সমাধানের সাথে কী ঘটে;

for(var i = 0; i < 10; i++) {
  (function(){
    var i2 = i;
    setTimeout(function(){
        console.log(i2); //i2 is undefined in JavaScript-No-Closure 
    }, 1000)
  })();
}

সুতরাং এটি undefinedজাভাস্ক্রিপ্ট-নো-ক্লোজারে 10 বার মুদ্রণ করবে ।

সুতরাং প্রথম সমাধানটি ক্লোজার ব্যবহার করে।

দ্বিতীয় সমাধানটি দেখি;

for(var i = 0; i < 10; i++) {
  setTimeout((function(i2){
    return function() {
        console.log(i2); //i2 is undefined in JavaScript-No-Closure
    }
  })(i), 1000);
}

সুতরাং এটি undefinedজাভাস্ক্রিপ্ট-নো-ক্লোজারে 10 বার মুদ্রণ করবে ।

উভয় সমাধান ক্লোজার ব্যবহার করে।

সম্পাদনা করুন: ধারণা করা হয় যে এই 3 টি কোড স্নিপেটগুলি বিশ্বব্যাপী সুযোগে সংজ্ঞায়িত করা হয়নি। তা না হলে ভেরিয়েবল fooএবং iপ্রদানকারীর সাথে যুক্ত হন হবে windowবস্তু এবং সেইজন্য মাধ্যমে অ্যাক্সেসযোগ্য windowউভয় জাভাস্ক্রিপ্ট এবং JavaScript-কোন-বন্ধ বস্তুর।


কেন iঅপরিশোধিত করা উচিত ? আপনি কেবল প্যারেন্ট স্কোপটি উল্লেখ করুন, যদি কোনও বন্ধকরণ না থাকে তবে এটি এখনও বৈধ।
লীমস

জাভা স্ক্রিপ্ট-নো-ক্লোজারে ফু যেমন অপরিজ্ঞাত রয়েছে একই কারণে। <code> i </code> জাভাস্ক্রিপ্টে অপরিজ্ঞাত নয় জাভা স্ক্রিপ্টের এমন একটি বৈশিষ্ট্যের জন্য ধন্যবাদ যা লেক্সিক্যাল প্যারেন্টে বর্ণিত ভেরিয়েবল অ্যাক্সেস করতে দেয়। এই বৈশিষ্ট্যটিকে ক্লোজার বলা হয়।
চমত্কার

আপনি ইতিমধ্যে সংজ্ঞায়িত ভেরিয়েবল এবং ফ্রি ভেরিয়েবল উল্লেখ করার মধ্যে পার্থক্য বুঝতে পারেন নি । ক্লোজারগুলিতে, আমরা ফ্রি ভেরিয়েবলগুলি সংজ্ঞায়িত করি যা বাইরের প্রসঙ্গে আবদ্ধ থাকতে হয়। আপনার কোডটিতে আপনি যখন আপনার ফাংশনটি সংজ্ঞায়িত করেন ঠিক তখনই আপনি সেট আপ i2 করেছিলেন i। এটি iএকটি বিনামূল্যে পরিবর্তনশীল করে তোলে না। তবুও, আমরা আপনার ফাংশনটিকে একটি ক্লোজার হিসাবে বিবেচনা করি, তবে কোনও বিনা ভেরিয়েবল ছাড়াই এটি মূল বিষয়।
লীমস

2
@ লেইমস, আমি সম্মত এবং গৃহীত উত্তরের তুলনায়, এটি আসলে কী ঘটছে তা প্রকৃতপক্ষে প্রদর্শন করে না। :)
আবেল

3
আমি মনে করি এটি সর্বোত্তম উত্তর, ক্লোজারগুলি সাধারণভাবে এবং সহজভাবে ব্যাখ্যা করে এবং তারপরে নির্দিষ্ট ব্যবহারের ক্ষেত্রে চলে যায়। ধন্যবাদ!
টিম পিটারসন

22

যেভাবে কেউ এটি ব্যাখ্যা করে আমি কখনই খুশি হইনি।

ক্লোজারগুলি বোঝার মূল চাবিকাঠিটি বন্ধ হওয়া ছাড়া জেএস কেমন হবে তা বোঝা।

বন্ধ না করে, এটি একটি ত্রুটি নিক্ষেপ করবে

function outerFunc(){
    var outerVar = 'an outerFunc var';
    return function(){
        alert(outerVar);
    }
}

outerFunc()(); //returns inner function and fires it

একবার জাভাস্ক্রিপ্টের একটি কাল্পনিক বন্ধ-অক্ষম সংস্করণে আউটআরফ্যান্স ফিরে আসার পরে, আউটওয়ারভারের উল্লেখটি আবর্জনা সংগ্রহ করা হবে এবং অভ্যন্তরীণ ফানক রেফারেন্সের জন্য কিছুই রেখে যায় না।

বন্ধকরণগুলি মূলত সেই বিশেষ নিয়ম যা লিক ইন করে এবং যখন কোনও অভ্যন্তরীণ ফাংশন বাইরের ফাংশনের ভেরিয়েবলগুলি উল্লেখ করে তখন সেইগুলিগুলির উপস্থিতিগুলি সম্ভব করে তোলে। ক্লোজারগুলির সাথে বাইরের ফাংশনটি সম্পন্ন করার পরে বা 'বন্ধ' করার পরেও রেফারেন্সযুক্ত ওয়ারগুলি বজায় রাখা হয় যদি এটি আপনাকে পয়েন্টটি মনে রাখতে সহায়তা করে।

এমনকি বন্ধ হয়ে যাওয়ার পরেও, কোনও স্থানীয় অভ্যন্তরীন ফানকসহীন একটি ফাংশনে স্থানীয় যুদ্ধের জীবনচক্রটি যা এর স্থানীয়দের উল্লেখ করে এটি ক্লোজার-কম সংস্করণে যেমন কাজ করে। অনুষ্ঠান শেষ হলে স্থানীয়রা আবর্জনা সংগ্রহ করেন get

একবার আপনি যদি কোনও বাহ্যিক বর্ণের অভ্যন্তরীণ বিন্দুতে কোনও রেফারেন্স পান তবে এটি দরজা জাম্বের মতো সেই রেফারেন্সযুক্ত ভারগুলির জন্য আবর্জনা সংগ্রহের পথে ফেলে দেওয়া হয়।

বন্ধগুলি দেখার জন্য সম্ভবত আরও সঠিক উপায় হ'ল অভ্যন্তরীণ ফাংশনটি মূলত অভ্যন্তরীণ সুযোগটিকে তার নিজস্ব স্কোপ ফাউন্ডেশন হিসাবে ব্যবহার করে।

তবে উল্লেখ করা প্রসঙ্গটি আসলে, অবিচলিত, কোনও স্ন্যাপশটের মতো নয়। বারবার পুনরুদ্ধার করা একটি অভ্যন্তরীণ ফাংশন ফায়ার করা যা বহিরাগত ফাংশনটির স্থানীয় ভেরাকে বাড়িয়ে দেওয়া এবং লগ করতে থাকে উচ্চতর মানগুলিকে সতর্ক করে।

function outerFunc(){
    var incrementMe = 0;
    return function(){ incrementMe++; console.log(incrementMe); }
}
var inc = outerFunc();
inc(); //logs 1
inc(); //logs 2

আপনি 'স্ন্যাপশট' সম্পর্কে ঠিক বলেছেন (আমার ধারণা, আপনি আমার উত্তরটি উল্লেখ করেছেন) by আমি এমন একটি শব্দ খুঁজছিলাম যা আচরণটি নির্দেশ করবে। আপনার উদাহরণে এটি 'হটলিংক' বন্ধকরণ নির্মাণ হিসাবে দেখা যেতে পারে। অভ্যন্তরীণ ফাংশনে প্যারামিটার হিসাবে ক্লোজারটি ধরার সময়, কেউ বলতে পারে যে এটি 'স্ন্যাপশট' হিসাবে আচরণ করে। তবে আমি একমত, অপব্যবহার করা শব্দগুলি কেবল বিষয়টিতে বিভ্রান্তি যুক্ত করে। সে সম্পর্কে আপনার কোনও পরামর্শ থাকলে আমি আমার উত্তর আপডেট করব।
অ্যান্ডরিস

আপনি যদি অভ্যন্তরীণ ফাংশনটি একটি নামকৃত ফাংশন দেন তবে এটি ব্যাখ্যায় সহায়তা করতে পারে।
ফিলিপ সেন

বন্ধ না করে আপনি একটি ত্রুটি পাবেন কারণ আপনি একটি ভেরিয়েবল ব্যবহার করার চেষ্টা করছেন যা বিদ্যমান নেই।
জুয়ান মেন্ডেস

হুম ... ভাল কথা। কোনও অপরিজ্ঞাত বর্ণের উল্লেখ করা কি কখনও ত্রুটি ছুঁড়েছিল না কারণ এটি চূড়ান্তভাবে বিশ্বব্যাপী কোনও সামগ্রীর সম্পত্তি হিসাবে দেখাবে বা আমি অপরিজ্ঞাত ওয়ারগুলিতে অ্যাসাইনমেন্ট দিয়ে বিভ্রান্ত করছি?
এরিক রেপেন

17

আপনি উভয় ক্লোজার ব্যবহার করছেন।

আমি এখানে উইকিপিডিয়া সংজ্ঞা নিয়ে যাচ্ছি :

কম্পিউটার সায়েন্সে ক্লোজার (লেজিকাল ক্লোজার বা ফাংশন ক্লোজার) হ'ল একটি ফাংশন বা রেফারেন্সিং পরিবেশের সাথে কোনও ফাংশনের রেফারেন্স - একটি টেবিল যে ফাংশনের অ-লোকাল ভেরিয়েবলের (যাকে ফ্রি ভেরিয়েবলও বলা হয়) প্রত্যেকটির রেফারেন্স সংরক্ষণ করে table । একটি সমাপ্তি - একটি সমতল ফাংশন পয়েন্টারের বিপরীতে a কোনও ফাংশনকে সেই অ-স্থানীয় ভেরিয়েবলগুলিকে অ্যাক্সেস করার অনুমতি দেয় এমনকি তার তাত্ক্ষণিক লেক্সিকাল স্কোপের বাইরেও অনুরোধ করা হয়।

আপনার বন্ধুর প্রয়াস স্পষ্টভাবে ভেরিয়েবলটি ব্যবহার করে i, যা স্থানীয় নয়, এর মূল্য গ্রহণ করে এবং লোকালগুলিতে সঞ্চয় করার জন্য একটি অনুলিপি তৈরি করে i2

আপনার নিজস্ব প্রয়াসটি i(যা কল সাইটে রয়েছে সেই সুযোগটি যুক্তি হিসাবে) একটি বেনামী ফাংশনে চলে যায়। এটি এখন অবধি বন্ধ নয়, তবে তারপরে সেই ফাংশনটি অন্য একটি ফাংশনটি দেয় যা একইটিকে উল্লেখ করে i2। যেহেতু অভ্যন্তরের অনামী ফাংশনটি i2স্থানীয় নয়, এটি একটি বন্ধন তৈরি করে।


হ্যাঁ, তবে আমি মনে করি মূল বিষয়টি তিনি কীভাবে এটি করছেন। তিনি কেবল অনুলিপি iকরেন i2, তারপরে কিছু যুক্তি সংজ্ঞায়িত করেন এবং এই ফাংশনটি সম্পাদন করেন। আমি চাই চালানো তা অবিলম্বে কিন্তু এটি একটি Var মধ্যে সঞ্চয় করবে এবং লুপ পরে এটি মৃত্যুদন্ড কার্যকর করা, এটা 10 প্রিন্ট হবে, তাই নয় কি? সুতরাং এটি হয়নি না আমি আকর্ষন করুন।
লীমস

6
@ লেলিজ: এটি iঠিক আছে। আপনি যে আচরণটি বর্ণনা করছেন তা বন্ধের বনাম অ-ক্লোজারের ফলাফল নয়; এরই মধ্যে এটি ক্লোজ-ওভার ভেরিয়েবলের পরিবর্তনের ফলাফল। আপনি তাত্ক্ষণিকভাবে কোনও ফাংশন কল করে এবং iএকটি আর্গুমেন্ট হিসাবে (যা ঘটনাস্থলে এর বর্তমান মানটি অনুলিপি করে) আলাদা সিনট্যাক্স ব্যবহার করে একই জিনিস করছেন । আপনি নিজের setTimeoutভিতরে অন্যের ভিতরে রাখলে setTimeoutএকই ঘটনা ঘটবে।
জন

13

আপনি এবং আপনার বন্ধু উভয় ক্লোজার ব্যবহার করেন:

ক্লোজার হ'ল একটি বিশেষ ধরণের অবজেক্ট যা দুটি জিনিসকে একত্রিত করে: একটি ফাংশন এবং সেই পরিবেশটি যেখানে সেই ফাংশনটি তৈরি হয়েছিল। পরিবেশটি এমন কোনও স্থানীয় ভেরিয়েবল নিয়ে গঠিত যা ক্লোজারটি তৈরির সময় সীমাবদ্ধ ছিল।

MDN: https://developer.mozilla.org/en-US/docs/ জাভা স্ক্রিপ্ট / গুয়াইড / ক্লোজার

আপনার বন্ধুর কোড ফাংশনে function(){ console.log(i2); }বেনামে ফাংশন বন্ধ করার সংজ্ঞা দেওয়া হয়েছে function(){ var i2 = i; ...এবং স্থানীয় ভেরিয়েবলটি পড়তে / লিখতে পারে i2

আপনার কোড ফাংশনে ফাংশন function(){ console.log(i2); }বন্ধের মধ্যে সংজ্ঞায়িত হয়েছে function(i2){ return ...এবং স্থানীয় মূল্যবান পড়তে / লিখতে পারেন i2(এই ক্ষেত্রে প্যারামিটার হিসাবে ঘোষণা করা হয়েছে)

উভয় ক্ষেত্রেই ফাংশন function(){ console.log(i2); }পরে পাস setTimeout

অন্য সমতুল্য (তবে কম স্মৃতি ব্যবহারের সাথে) হ'ল:

function fGenerator(i2){
    return function(){
        console.log(i2);
    }
}
for(var i = 0; i < 10; i++) {
    setTimeout(fGenerator(i), 1000);
}

1
আমি দেখতে পাচ্ছি না কেন আপনার সমাধান বনাম আমার বন্ধুর সমাধান "আরও দ্রুত এবং কম স্মৃতি ব্যবহারের সাথে", আপনি কী ব্যাখ্যা করতে পারেন?
চমত্কার

3
আপনার সমাধানে আপনি 20 ফাংশন অবজেক্ট (প্রতিটি লুপে 2 টি অবজেক্ট: 2x10 = 20) তৈরি করেন। আপনার ফ্রেন্ড সমাধানের একই ফলাফল। "আমার" সমাধানে কেবল 11 টি ফাংশন তৈরি করা হয়: লুপের জন্য 1 এবং 10 "ভিতরে" - 1 + 1x10 = 11। ফলস্বরূপ - কম স্মৃতি ব্যবহার এবং গতি বৃদ্ধি।
অ্যান্ড্রু ডি

1
তত্ত্বগতভাবে, এটি সত্য হবে। অনুশীলনে, এছাড়াও: এই জেএসপিফার মানদণ্ডটি দেখুন: jsperf.com/closure-vs-name-function-in-a-loop/2
রব ডব্লু

10

অবসান

একটি বন্ধকরণ কোনও ক্রিয়াকলাপ নয় এবং কোনও অভিব্যক্তি নয়। এটি অবশ্যই ফাংশনস্কোপের বাইরে ব্যবহৃত ভেরিয়েবলগুলি থেকে একধরণের 'স্ন্যাপশট' হিসাবে দেখা উচিত এবং ফাংশনের অভ্যন্তরে ব্যবহৃত হবে। ব্যাকরণগতভাবে, একটি বলা উচিত: 'ভেরিয়েবল বন্ধ করুন'।

আবার, অন্য কথায়: একটি ক্লোজার হল ভেরিয়েবলগুলির প্রাসঙ্গিক প্রসঙ্গে একটি অনুলিপি যার উপর ফাংশন নির্ভর করে।

আরও একবার (নাফ): একটি বন্ধে এমন ভেরিয়েবলগুলির অ্যাক্সেস রয়েছে যা প্যারামিটার হিসাবে পাস হচ্ছে না।

মনে রাখবেন যে এই কার্যকরী ধারণাগুলি আপনার ব্যবহৃত প্রোগ্রামিং ভাষা / পরিবেশের উপর দৃ .়ভাবে নির্ভর করে। জাভাস্ক্রিপ্টে, বন্ধটি লেক্সিকাল স্কোপিংয়ের উপর নির্ভর করে (যা বেশিরভাগ সি-ভাষায় সত্য)।

সুতরাং, একটি ফাংশন ফিরে আসা বেশিরভাগই একটি বেনাম / নামবিহীন ফাংশনটি ফিরিয়ে দেয়। যখন ফাংশন অ্যাক্সেস ভেরিয়েবলগুলি, প্যারামিটার হিসাবে পাস না করা হয় এবং এর (লেক্সিকাল) স্কোপের মধ্যে, একটি বন্ধ হয়ে যায়।

সুতরাং, আপনার উদাহরণগুলি সম্পর্কে:

// 1
for(var i = 0; i < 10; i++) {
    setTimeout(function() {
        console.log(i); // closure, only when loop finishes within 1000 ms,
    }, 1000);           // i = 10 for all functions
}
// 2
for(var i = 0; i < 10; i++) {
    (function(){
        var i2 = i; // closure of i (lexical scope: for-loop)
        setTimeout(function(){
            console.log(i2); // closure of i2 (lexical scope:outer function)
        }, 1000)
    })();
}
// 3
for(var i = 0; i < 10; i++) {
    setTimeout((function(i2){
        return function() {
            console.log(i2); // closure of i2 (outer scope)

        }
    })(i), 1000); // param access i (no closure)
}

সবাই ক্লোজার ব্যবহার করছে। সমাপনীকরণের সাথে ফাঁসির বিন্দুটি গুলিয়ে ফেলবেন না। বন্ধের 'স্ন্যাপশট'টি যদি ভুল মুহুর্তে নেওয়া হয় তবে মানগুলি অপ্রত্যাশিত হতে পারে তবে অবশ্যই একটি বন্ধ হয়ে যায়!



10

আসুন দুটি উপায় দেখুন:

(function(){
    var i2 = i;
    setTimeout(function(){
        console.log(i2);
    }, 1000)
})();

ঘোষণা করে এবং তাত্ক্ষণিকভাবে একটি অনামী ফাংশন কার্যকর করে যা setTimeout()তার নিজস্ব প্রসঙ্গে চলে। এর বর্তমান মানটি প্রথমে iঅনুলিপি করে সংরক্ষণ করা হয় i2; এটি তাত্ক্ষণিকভাবে কার্যকর করার কারণে কাজ করে।

setTimeout((function(i2){
    return function() {
        console.log(i2);
    }
})(i), 1000);

অভ্যন্তরীণ ফাংশনটির জন্য একটি কার্যকরকরণ প্রসঙ্গ ঘোষণা করে যার বর্তমান মানটি এতে iসংরক্ষণ করা হয় i2; এই পদ্ধতির মান সংরক্ষণের জন্য তাত্ক্ষণিক কার্যকরকরণও ব্যবহৃত হয়।

গুরুত্বপূর্ণ

এটি উল্লেখ করা উচিত যে রান শব্দার্থক উভয় পদ্ধতির মধ্যে এক নয়; আপনার অভ্যন্তরীণ ফাংশনটি setTimeout()তার অভ্যন্তরের ফাংশনটি কল করার সময় চলে setTimeout()যায়।

অন্য কোডের মধ্যে উভয় কোড মোড়ানো setTimeout()প্রমাণ করে না যে কেবলমাত্র দ্বিতীয় পদ্ধতির ক্লোজার ব্যবহার করা হয়, শুরু করার মতো একই জিনিস নেই।

উপসংহার

উভয় পদ্ধতি ক্লোজার ব্যবহার করে, তাই এটি ব্যক্তিগত স্বাদে নেমে আসে; দ্বিতীয় পদ্ধতিটি "সরানো" কাছাকাছি বা সাধারণকরণ সহজ।


আমি মনে করি পার্থক্যটি: তার সমাধান (1 ম) রেফারেন্স দ্বারা ক্যাপচার করছে, খনি (2 য়) মান দ্বারা ক্যাপচার করছে। এই ক্ষেত্রে এটি কোনও তাত্পর্যপূর্ণ করে না, তবে যদি আমি নির্বাহটিকে অন্য সেটটাইমআউটে রাখি তবে আমরা দেখতে পাব যে তার সমাধানটিতে সমস্যা রয়েছে যে এটি তার পরে i এর চূড়ান্ত মান ব্যবহার করে, বর্তমানের নয়, যখন আমার সিল ব্যবহার করে বর্তমান মান (যেহেতু মান দ্বারা ক্যাপচার)
লীমস

@ লেলিমস আপনি উভয় একই ভাবে ক্যাপচার; ফাংশন আর্গুমেন্ট বা অ্যাসাইনমেন্টের মাধ্যমে একটি ভেরিয়েবল পাস করা একই জিনিস ... আপনি কীভাবে অন্যটিকে ফাঁসির কাজটি গুটিয়ে ফেলবেন আপনার প্রশ্নটিতে আপনি যুক্ত করতে পারেন setTimeout()?
জ্যাক 9

আমাকে এটি পরীক্ষা করে দেখাতে দাও ... আমি এটি দেখাতে চেয়েছিলাম যে ফাংশনটি অজানা হয়ে যেতে পারে এবং iকোথায় বা কখন আমরা এটি সম্পাদন করব তার উপর নির্ভর করে ফাংশনটি কী প্রিন্ট করে তা প্রভাবিত না করে মূল পরিবর্তনশীল পরিবর্তন করা যেতে পারে।
লীমস

অপেক্ষা করুন, আপনি কোনও ফাংশন (বাইরের) সেটটাইমআউটে পাস করেননি। ()এগুলি সরিয়ে ফেলুন , এভাবে একটি ফাংশন পেরিয়ে যাচ্ছেন এবং আপনি 10 বার আউটপুট দেখতে পাবেন 10
লীমস

@ লেলেমস যেমন পূর্বে উল্লিখিত হয়েছে, ()ঠিক তেমনই যা আপনার কোডকে ঠিক তেমন কাজ করে (i); আপনি কেবল তার কোডটি মোড়েননি, আপনি এতে পরিবর্তন করেছেন .. সুতরাং আপনি আর বৈধ তুলনা করতে পারবেন না।
Ja͢ck

8

বন্ধ হওয়া কী এবং কীভাবে এটি জেএসে কাজ করে তা স্মরণ করিয়ে দেওয়ার জন্য আমি কিছুক্ষণ আগে এটি লিখেছিলাম।

ক্লোজার হ'ল এমন একটি ফাংশন যা বলা হয়, এটি যে স্কোপ হিসাবে ঘোষিত হয়েছিল তা ব্যবহার করে, যেখানে তাকে ডাকা হয়েছিল তার সুযোগ নয়। জাভাস্ক্রিপ্টে, সমস্ত ফাংশন এ জাতীয় আচরণ করে। স্ক্যাপের পরিবর্তনশীল মানগুলি ততক্ষণ স্থায়ী থাকে যতক্ষণ না কোনও ক্রিয়া থাকে যা এখনও তাদের দেখায়। নিয়মের ব্যতিক্রম হ'ল 'এটি', যা ফাংশনটি যখন ডাকা হয় তখন ভিতরে থাকা সেই বস্তুকে বোঝায়।

var z = 1;
function x(){
    var z = 2; 
    y(function(){
      alert(z);
    });
}
function y(f){
    var z = 3;
    f();
}
x(); //alerts '2' 

6

ঘনিষ্ঠভাবে পরিদর্শন করার পরে দেখে মনে হচ্ছে আপনি উভয় ক্লোজার ব্যবহার করছেন।

আপনার বন্ধুদের ক্ষেত্রে, iবেনামে ফাংশন 1 এর ভিতরে i2অ্যাক্সেস করা হয় এবং বেনামি ফাংশন 2 console.logএ উপস্থিত থাকে যেখানে উপস্থিত রয়েছে।

আপনার ক্ষেত্রে আপনি i2যেখানে console.logউপস্থিত রয়েছেন বেনামে ফাংশনটিতে প্রবেশ করছেন । "স্কোপ ভেরিয়েবল" এর অধীনে ক্রোম বিকাশকারী সরঞ্জামগুলির debugger;আগে console.logএবং এর আগে একটি বিবৃতি যুক্ত করুন এটি ভেরিয়েবলটি কী স্কোপের অধীনে তা জানিয়ে দেবে।


2
ডান প্যানেলে "সমাপ্তি" বিভাগটি ব্যবহৃত হয়েছে কারণ এর বেশি নির্দিষ্ট নাম নেই। "স্থানীয়" "বন্ধ" এর চেয়ে শক্তিশালী ইঙ্গিত।
রব ডব্লু


4

নিম্নোক্ত বিবেচনা কর. এটি একটি ফাংশন তৈরি করে এবং এটি পুনরায় তৈরি করে fযা বন্ধ হয় iতবে ভিন্ন ভিন্ন!:

i=100;

f=function(i){return function(){return ++i}}(0);
alert([f,f(),f(),f(),f(),f(),f(),f(),f(),f(),f()].join('\n\n'));

f=function(i){return new Function('return ++i')}(0);        /*  function declarations ~= expressions! */
alert([f,f(),f(),f(),f(),f(),f(),f(),f(),f(),f()].join('\n\n'));

যখন নিম্নলিখিতগুলি "একটি" ফাংশন "নিজেই" বন্ধ হয়ে যায়
(নিজেরাই! এটির পরে একটি স্নিগ্ধ ব্যবহার করার পরে স্নিপেট f)

for(var i = 0; i < 10; i++) {
    setTimeout( new Function('console.log('+i+')'),  1000 );
}

বা আরও স্পষ্ট করে বলতে:

for(var i = 0; i < 10; i++) {
    console.log(    f = new Function( 'console.log('+i+')' )    );
    setTimeout( f,  1000 );
}

বিশেষ দ্রষ্টব্য। শেষ সংজ্ঞা fহল function(){ console.log(9) } সামনে 0 ছাপা হয়।

সতর্কীকরণ! ক্লোজার ধারণাটি প্রাথমিক প্রোগ্রামিংয়ের সারাংশ থেকে বাধ্যতামূলক বিভ্রান্তি হতে পারে:

for(var i = 0; i < 10; i++) {     setTimeout( 'console.log('+i+')',  1000 );      }

এক্স-রেফস .:
জাভাস্ক্রিপ্ট ক্লোজারগুলি কীভাবে কাজ করবে?
জাভাস্ক্রিপ্ট বন্ধের ব্যাখ্যা
কি কোনও (জেএস)
বন্ধের কোনও ফাংশনের অভ্যন্তরে কোনও ফাংশনের প্রয়োজন আছে জাভাস্ক্রিপ্টে ক্লোজারগুলি কীভাবে বোঝা যায়?
জাভাস্ক্রিপ্ট স্থানীয় এবং বৈশ্বিক পরিবর্তনশীল বিভ্রান্তি


স্নিপেটগুলি প্রথমবারের জন্য চেষ্টা করেছিল - কীভাবে নিয়ন্ত্রণ করা যায় তা নিশ্চিত নয় - Run' only was desired - not sure how to remove the অনুলিপি
একিম

-1

আমি আমার উদাহরণ এবং বন্ধ সম্পর্কে একটি ব্যাখ্যা ভাগ করতে চাই। আমি একটি অজগর উদাহরণ তৈরি করেছি এবং স্ট্যাকের রাজ্যগুলি প্রদর্শন করার জন্য দুটি চিত্র।

def maker(a, b, n):
    margin_top = 2
    padding = 4
    def message(msg):
        print('\n * margin_top, a * n, 
            ' ‘ * padding, msg, '  * padding, b * n)
    return message

f = maker('*', '#', 5)
g = maker('', '♥’, 3)

f('hello')
g(‘good bye!')

এই কোডের আউটপুট নীচে হবে:

*****      hello      #####

      good bye!    ♥♥♥

ফাংশন অবজেক্টের সাথে স্ট্যাক এবং ক্লোজারটি দেখানোর জন্য এখানে দুটি চিত্র রয়েছে।

যখন ফাংশনটি প্রস্তুতকারকের কাছ থেকে ফিরে আসে

যখন ফাংশনটি পরে বলা হয়

যখন প্যারামিটার বা ননলোকাল ভেরিয়েবলের মাধ্যমে ফাংশনটি কল করা হয়, কোডটির জন্য স্থানীয় ভেরিয়েবল বাইন্ডিং যেমন মার্জিন_টপ, প্যাডিং পাশাপাশি ক, বি, এন প্রয়োজন হয়। কাজ করার জন্য ফাংশন কোডটি নিশ্চিত করার জন্য, মেকার ফাংশনের স্ট্যাক ফ্রেমটি যা অনেক আগে চলে গিয়েছিল তা অ্যাক্সেসযোগ্য হওয়া উচিত, যা বন্ধকরণে ব্যাক আপ করা হয়েছে যা আমরা ফাংশন বার্তার অবজেক্টের সাথে দেখতে পাই।


আমি এই উত্তরটি মুছে ফেলতে চাই। আমি বুঝতে পেরেছি যে প্রশ্নটি কী বন্ধ তা নিয়ে নয়, তাই আমি এটিকে অন্য প্রশ্নের দিকে নিয়ে যেতে চাই।
ইউঞ্জং লি

2
আমি বিশ্বাস করি আপনার নিজস্ব সামগ্রী মুছে ফেলার ক্ষমতা আছে। deleteউত্তরের লিঙ্কে ক্লিক করুন ।
ররি ম্যাকক্রসন
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.