লেক্সিকাল স্কোপ কি?


682

লেক্সিকাল স্কোপিংয়ের সংক্ষিপ্ত পরিচিতি কী?


89
পডকাস্ট 58 এ, জোয়েল প্রশ্নগুলির পছন্দগুলিকে উত্সাহিত করে কারণ তিনি অন্য জায়গাগুলিতে উত্তর দেওয়া হলেও, উত্তরগুলির জায়গা হয়ে যেতে চান। এটি একটি বৈধ প্রশ্ন, যদিও কেউ এটিকে আরও কিছুটা নম্র করে তুলতে পারে।
রাল্ফ এম। রিকেনবাচ

5
@ রহুল আমি বুঝতে পারছি এটি একটি পুরানো প্রশ্ন। তবে আমি নিশ্চিত যে ২০০৯ সালেও এসও আশা করেছিলেন যে এটি সমাধানের দিকে কিছু মৌলিক প্রচেষ্টা চালাবে । এটি যেমন দাঁড়িয়েছে তেমন কোনও প্রচেষ্টা দেখায় না । হতে পারে, এ কারণেই এটি অনেকের দ্বারা ডাউনওয়েট হয়েছিল?
পিপি

13
এই প্রশ্নটি লেখার সময় প্রশ্নকর্তা ইংরেজিতে অনর্গল (বা ছিলেন না) সম্ভব
মার্টিন

27
প্রশ্নটি ভদ্র, তিনি যা চান তা কেবলই বলেছেন। আপনি উত্তর দিতে নির্দ্বিধায়। এখানে অলসনেসিবল রাজনীতির দরকার নেই।
মার্কাস সিবেনিচার

25
আমি মনে করি এর মতো প্রশ্নগুলি দুর্দান্ত কারণ এটি এসও এর জন্য সামগ্রী তৈরি করে। আইএমও, যারা এই প্রশ্নটির চেষ্টা না করে সেদিকে খেয়াল রাখে ... উত্তরের দুর্দান্ত বিষয়বস্তু থাকবে এবং এই বার্তা বোর্ডের ক্ষেত্রে এটিই গুরুত্বপূর্ণ।
Jwan622

উত্তর:


686

আমি উদাহরণের মাধ্যমে তাদের বুঝতে। :)

প্রথমত, সি-এর মতো সিনট্যাক্সে লেজিকাল স্কোপ (এটি স্ট্যাটিক স্কোপ নামেও পরিচিত ):

void fun()
{
    int x = 5;

    void fun2()
    {
        printf("%d", x);
    }
}

প্রতিটি অভ্যন্তরীণ স্তর এর বাইরের স্তরগুলিতে অ্যাক্সেস করতে পারে।

লিস্পের প্রথম বাস্তবায়নের মাধ্যমে গতিশীল স্কোপ নামে একটি অন্য উপায় রয়েছে যা আবার সি-এর মতো বাক্য গঠনতে ব্যবহৃত হয় :

void fun()
{
    printf("%d", x);
}

void dummy1()
{
    int x = 5;

    fun();
}

void dummy2()
{
    int x = 10;

    fun();
}

এখানে funপারেন অ্যাক্সেস করা যাবে xমধ্যে dummy1বা dummy2, বা কোনো xযে কলে যেকোনো ফাংশনে funসঙ্গে xএটা ঘোষিত।

dummy1();

5 মুদ্রণ করবে,

dummy2();

10 মুদ্রণ করবে।

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

আমি চোখের জন্য স্থির স্কোপিংকে আরও সহজ মনে করি। বেশিরভাগ ভাষা শেষ পর্যন্ত এইভাবে চলে গেছে, এমনকি লিস্প (উভয়ই করতে পারে, তাই না?) ডায়নামিক স্কোপিং হ'ল ফাংশনে সমস্ত ভেরিয়েবলের রেফারেন্স দেওয়ার মতো।

সংকলক কেন কোনও ফাংশনের বাইরের গতিশীল সুযোগকে কমিয়ে দিতে পারে না তার একটি উদাহরণ হিসাবে, আমাদের শেষ উদাহরণটি বিবেচনা করুন। আমরা যদি এরকম কিছু লিখি:

if(/* some condition */)
    dummy1();
else
    dummy2();

কল চেইন রান টাইম শর্তের উপর নির্ভর করে। যদি এটি সত্য হয়, তবে কল চেইনটি এমন দেখাচ্ছে:

dummy1 --> fun()

শর্তটি মিথ্যা হলে:

dummy2 --> fun()

funউভয় ক্ষেত্রেই বাহ্যিক সুযোগ হ'ল কলার প্লাস কলারের কলস এবং আরও অনেক কিছু

কেবল উল্লেখ করার জন্য যে সি ভাষা নেস্টেড ফাংশন বা গতিশীল স্কোপিংয়ের অনুমতি দেয় না।


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

9
এটি একটি ভাল উত্তর। তবে প্রশ্নটি ট্যাগ করা আছে JavaScript। অতএব আমি মনে করি এটি গ্রহণযোগ্য উত্তর হিসাবে চিহ্নিত করা উচিত নয়। জেএসে বিশেষত লেক্সিকাল স্কোপটি আলাদা
বায়াং

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

4
প্রথমদিকে আমি ভেবেছিলাম উদাহরণটি বৈধ সি কোড ছিল এবং বিভ্রান্ত হয়ে পড়েছিল কিনা সি-তে গতিশীল স্কোপিং ছিল কিনা শেষ পর্যন্ত অস্বীকৃতি কোডের উদাহরণের আগে স্থানান্তরিত হতে পারে?
ইয়াংশুন তাই

2
এটি এখনও একটি খুব সহায়ক উত্তর তবে আমি মনে করি @ বোয়াং সঠিক। এই উত্তরটি 'স্তর' বোঝায়, যা ব্লগ স্কোপের লাইনের সাথে আরও বেশি রয়েছে। ডিফল্টভাবে জাভাস্ক্রিপ্টের ব্লক স্তরের সুযোগ নেই, সুতরাং একটি forলুপের অভ্যন্তরে সাধারণ সমস্যা। ES6 letবা constব্যবহৃত না হলে জাভাস্ক্রিপ্টের জন্য লেজিকাল স্কোপটি কেবলমাত্র ফাংশন স্তরে থাকে ।
icc97

274

সংক্ষিপ্ততম সংজ্ঞাটি চেষ্টা করতে দিন:

লেক্সিকাল স্কোপিং সংজ্ঞায়িত করে যে কীভাবে ভেরিয়েবলের নামগুলি নেস্টেড ফাংশনগুলিতে সমাধান করা হয়: অভ্যন্তরীণ ফাংশনগুলিতে প্যারেন্ট ফাংশনগুলি ফিরে আসে এমনকি পিতামাতার ফাংশনগুলির সুযোগ থাকে

এটাই তো আছে!


21
শেষ অংশ: "পিতামাতার ফাংশনটি ফিরে এলেও" ক্লোজার বলা হয়।
জুয়ানমা মেনেন্দেজ

1
মাত্র একটি প্রেরণে লেক্সিকাল স্কোপিং এবং ক্লোজার বোঝা। ধন্যবাদ !!
অন্ধকূপে

63
var scope = "I am global";
function whatismyscope(){
   var scope = "I am just a local";
   function func() {return scope;}
   return func;
}

whatismyscope()()

উপরের কোডটি "আমি কেবল স্থানীয়" ফিরে আসবে। এটি "আমি একটি বিশ্বব্যাপী" ফিরে আসবে না। কারণ ফাংশন ফানক () গণনা করে যেখানে মূলত সংজ্ঞা দেওয়া হয়েছিল যা ফাংশন হোয়াটিসিস্কোপের আওতায় রয়েছে।

এটি যাকে বলা হচ্ছে তা থেকে বিরত হবে না (বৈশ্বিক স্কোপ / এমনকি অন্য কোনও ফাংশনের মধ্যে থেকে), সে কারণেই আমি বিশ্বব্যাপী স্কোপ মানটি মুদ্রিত হবে না।

এটিকে লেক্সিকাল স্কোপিং বলা হয় যেখানে " স্কোপ চেইন ব্যবহার করে ফাংশনগুলি কার্যকর করা হয়েছিল যা তাদের সংজ্ঞায়িত করার সময় কার্যকর হয়েছিল " - জাভাস্ক্রিপ্ট সংজ্ঞা গাইড অনুসারে।

লেক্সিকাল স্কোপ একটি খুব শক্তিশালী ধারণা।

আশাকরি এটা সাহায্য করবে..:)


3
এটি খুব সুন্দর ব্যাখ্যা আমি আরও একটি জিনিস যুক্ত করতে চাই আপনি যদি ফাংশন ফানক লিখেন () {this.scope;} তবে এটি "আমি বিশ্বব্যাপী" ফিরে আসবে কেবল এই কীওয়ার্ডটি ব্যবহার করুন এবং আপনার
ক্ষেত্রটি

41

লেক্সিকাল (একেএ স্ট্যাটিক) স্কোপিং বলতে কোডের টেক্সচুয়াল কর্পাসের মধ্যে কেবল তার অবস্থানের ভিত্তিতে ভেরিয়েবলের স্কোপ নির্ধারণকে বোঝায়। একটি পরিবর্তনশীল সর্বদা এর শীর্ষ স্তরের পরিবেশকে বোঝায়। এটি ডায়নামিক স্কোপের সাথে বোঝা ভাল।


41

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

লেজিকাল অংশটির অর্থ আপনি উত্স কোডটি পড়া থেকে সুযোগটি অর্জন করতে পারেন।

লেক্সিকাল স্কোপ স্ট্যাটিক স্কোপ হিসাবেও পরিচিত।

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

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

গতিশীল সুযোগের জন্য একটি আকর্ষণীয় উদাহরণ দেখতে এখানে দেখুন

আরও তথ্যের জন্য এখানে এবং এখানে দেখুন

ডেলফি / অবজেক্ট পাসকালের কয়েকটি উদাহরণ

ডেলফির লেক্সিকাল স্কোপ রয়েছে।

unit Main;
uses aUnit;  // makes available all variables in interface section of aUnit

interface

  var aGlobal: string; // global in the scope of all units that use Main;
  type 
    TmyClass = class
      strict private aPrivateVar: Integer; // only known by objects of this class type
                                    // lexical: within class definition, 
                                    // reserved word private   
      public aPublicVar: double;    // known to everyboday that has access to a 
                                    // object of this class type
    end;

implementation

  var aLocalGlobal: string; // known to all functions following 
                            // the definition in this unit    

end.

গতিশীল স্কোপে সবচেয়ে কাছের ডেল্ফিটি হ'ল রেজিস্টারক্লাস () / গেটক্লাস () ফাংশন জুটি। এর ব্যবহারের জন্য এখানে দেখুন

ধরা যাক যে রেজিস্টারক্লাস ([TmyClass]) একটি নির্দিষ্ট শ্রেণীর নিবন্ধনের জন্য আহ্বান জানানো হয়েছে কোড পড়ার মাধ্যমে ভবিষ্যদ্বাণী করা যায় না (এটি ব্যবহারকারী দ্বারা বোতাম ক্লিক করার পদ্ধতিতে কল করা হয়), গেটক্লাস ('TmyClass') কলিং কোডটি পাবেন একটি ফলাফল বা না। রেজিস্টারক্লাস () এ কল করা গেটক্লাস () ব্যবহার করে ইউনিটের লেজিকাল স্কোপে থাকতে হবে না;

গতিশীল সুযোগের জন্য আর একটি সম্ভাবনা হ'ল ডেলফি ২০০৯ এ বেনামে পদ্ধতি (ক্লোজার), কারণ তারা তাদের কলিংয়ের ফাংশনের পরিবর্তনশীলগুলি জানেন। এটি পুনরাবৃত্তভাবে সেখান থেকে কলিংয়ের পথ অনুসরণ করে না এবং তাই সম্পূর্ণ গতিশীল নয়।


2
প্রকৃতপক্ষে গোটা ইউনিটে যেখানে ক্লাসটি সংজ্ঞায়িত হয় সেখানে ব্যক্তিগত প্রবেশযোগ্য। এই কারণেই D2006 এ "স্ট্রাইক প্রাইভেট" চালু হয়েছিল।
মার্কো ভ্যান ডি ভুর্ট

2
সরল ভাষার জন্য +1 (উভয় জটিল ভাষা এবং খুব বেশি বর্ণনা ছাড়াই উদাহরণগুলির বিপরীতে)
পোপস

36

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

জাভাস্ক্রিপ্টে স্কোপিংয়ের জন্য আমাদের পছন্দগুলি হ'ল:

  • যেমন রয়েছে (কোনও স্কোপ সমন্বয় নেই)
  • আভিধানিক var _this = this; function callback(){ console.log(_this); }
  • আবদ্ধ callback.bind(this)

আমি মনে করি, জাভাস্ক্রিপ্টের আসলে গতিশীল স্কোপিং নেই । কীওয়ার্ডটি .bindসামঞ্জস্য করে thisএবং এটি নিকটবর্তী, তবে প্রযুক্তিগতভাবে একই নয়।

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

আভিধানিক

এখানে Lexical Scopingআপনি জাভাস্ক্রিপ্টে কলব্যাকের শব্দটি বলতে পারেন :

var downloadManager = {
  initialize: function() {
    var _this = this; // Set up `_this` for lexical access
    $('.downloadLink').on('click', function () {
      _this.startDownload();
    });
  },
  startDownload: function(){
    this.thinking = true;
    // Request the file from the server and bind more callbacks for when it returns success or failure
  }
  //...
};

আবদ্ধ

সুযোগের অন্য উপায়টি হ'ল Function.prototype.bind:

var downloadManager = {
  initialize: function() {
    $('.downloadLink').on('click', function () {
      this.startDownload();
    }.bind(this)); // Create a function object bound to `this`
  }
//...

এই পদ্ধতিগুলি যতদূর আমি জানি, আচরণগতভাবে সমতুল্য।


ব্যবহারের bindসুযোগটি প্রভাবিত করে না।
বেন অ্যাস্টন

12

লেক্সিকাল স্কোপিং: কোনও ফাংশনের বাইরে ঘোষিত ভেরিয়েবলগুলি গ্লোবাল ভেরিয়েবল এবং একটি জাভাস্ক্রিপ্ট প্রোগ্রামে সর্বত্র দৃশ্যমান। কোনও ফাংশনের অভ্যন্তরে ঘোষিত ভেরিয়েবলগুলির ফাংশন স্কোপ থাকে এবং কেবলমাত্র সেই ফাংশনের অভ্যন্তরে প্রদর্শিত কোডের জন্য দৃশ্যমান।


12

আইবিএম এটিকে সংজ্ঞায়িত করে:

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

উদাহরণ 1:

function x() {
    /*
    Variable 'a' is only available to function 'x' and function 'y'.
    In other words the area defined by 'x' is the lexical scope of
    variable 'a'
    */
    var a = "I am a";

    function y() {
        console.log( a )
    }
    y();

}
// outputs 'I am a'
x();

উদাহরণ 2:

function x() {

    var a = "I am a";

    function y() {
         /*
         If a nested routine declares an item with the same name,
         the outer item is not available in the nested routine.
         */
        var a = 'I am inner a';
        console.log( a )
    }
    y();

}
// outputs 'I am inner a'
x();

8

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

function grandfather() {
    var name = 'Hammad';
    // 'likes' is not accessible here
    function parent() {
        // 'name' is accessible here
        // 'likes' is not accessible here
        function child() {
            // Innermost level of the scope chain
            // 'name' is also accessible here
            var likes = 'Coding';
        }
    }
}

লেজিকাল স্কোপ সম্পর্কে আপনি যে জিনিসটি লক্ষ্য করবেন সেটি হ'ল এটি এগিয়ে চলেছে, যার অর্থ নামটি বাচ্চাদের মৃত্যুদন্ড প্রসঙ্গ দ্বারা অ্যাক্সেস করা যেতে পারে। তবে এটি তার পিতামাতার পিছনে কাজ করে না, এর অর্থ হল likesএর পিতামাতার দ্বারা পরিবর্তনশীল অ্যাক্সেস করা যায় না।

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

মনে রাখবেন এটি এখান থেকে নেওয়া হয়েছে


8

সহজ ভাষায়, লেক্সিকাল স্কোপটি আপনার স্কোপের বাইরে সংজ্ঞায়িত একটি পরিবর্তনশীল বা উপরের স্কোপটি স্বয়ংক্রিয়ভাবে আপনার স্কোপের অভ্যন্তরে উপলব্ধ হয় যার অর্থ এটি আপনাকে সেখানে পাস করার দরকার নেই।

উদাহরণ:

let str="JavaScript";

const myFun = () => {
    console.log(str);
}

myFun();

// আউটপুট: জাভাস্ক্রিপ্ট


2
একটি উদাহরণ সহ আমার পক্ষে সবচেয়ে ছোট এবং সেরা উত্তর the ES6 'এর তীর ফাংশনগুলির সাহায্যে সমস্যাটি সমাধান করা যায় bind। তাদের সাথে, bindএখন আর দরকার নেই। এই পরিবর্তন সম্পর্কে আরও তথ্যের জন্য stackoverflow.com/a/34361380/11127383
ড্যানিয়েল ড্যানিয়েলেকি

4

সেখানে পার্শ্ববর্তী কথোপকথনের একটি গুরুত্বপূর্ণ অংশ আভিধানিক এবং গতিশীল scoping একটি প্লেইন ব্যাখ্যা: যে অনুপস্থিত জীবনকাল - বা বিশ্লেষণ করা ভেরিয়েবলের যখন পরিবর্তনশীল অ্যাক্সেস করতে পারবেন।

ডায়নামিক স্কোপিং কেবলমাত্র "গ্লোবাল" স্কোপিংয়ের সাথে সামঞ্জস্যপূর্ণ যেভাবে আমরা traditionতিহ্যগতভাবে এটি সম্পর্কে চিন্তা করি (যে কারণে আমি দুজনের মধ্যে তুলনা এনেছি তা ইতিমধ্যে উল্লেখ করা হয়েছে - এবং আমি বিশেষত লিঙ্কযুক্ত নিবন্ধের ব্যাখ্যা পছন্দ করি না ); এটি সম্ভবত সর্বোত্তম যে আমরা বৈশ্বিক এবং গতিশীলদের মধ্যে তুলনা করি না - যদিও অনুমিতভাবে, লিঙ্কযুক্ত নিবন্ধ অনুযায়ী, "... [এটি] বিশ্বব্যাপী স্কোপড ভেরিয়েবলের বিকল্প হিসাবে দরকারী" "

সুতরাং, সরল ইংরেজিতে, দুটি স্কোপিং প্রক্রিয়ার মধ্যে গুরুত্বপূর্ণ পার্থক্য কী?

উপরের উত্তরগুলিতে লেক্সিকাল স্কোপিংটি খুব ভালভাবে সংজ্ঞায়িত করা হয়েছে: লাক্ষিকভাবে স্কোপযুক্ত ভেরিয়েবলগুলি পাওয়া যায় - বা, অ্যাক্সেসযোগ্য - ফাংশনের স্থানীয় স্তরে যেখানে এটি সংজ্ঞায়িত হয়েছিল।

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

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

... [আমি] এন ডায়নামিক স্কোপিং (বা ডায়নামিক স্কোপ), যদি কোনও ভেরিয়েবল নামের স্কোপ একটি নির্দিষ্ট ফাংশন হয়, তবে এর সুযোগটি সময়-সময় যা চলাকালীন সঞ্চালিত হয়: ফাংশনটি চলমান অবস্থায়, ভেরিয়েবলের নামটি বিদ্যমান , এবং তার ভেরিয়েবলের সাথে আবদ্ধ, তবে ফাংশনটি ফিরে আসার পরে, ভেরিয়েবলের নামটি বিদ্যমান নেই।


3

লেক্সিকাল স্কোপটির অর্থ হল যে কোনও ফাংশনটি প্রাসঙ্গিকভাবে যেখানে সংজ্ঞায়িত হয়েছিল তার প্রকারে ভেরিয়েবলগুলি সন্ধান করে এবং তার আশেপাশের সুযোগে তা অবিলম্বে নয়।

আপনি আরও বিশদ জানতে চাইলে লিস্পে কীভাবে লেজিকাল স্কোপ কাজ করে তা দেখুন। ডায়নামিক এবং কমন লিস্পে লেক্সিকাল ভেরিয়েবলগুলিতে কাইল ক্রোনিনের নির্বাচিত উত্তর উত্তরগুলি এখানে উত্তরগুলির চেয়ে অনেক পরিষ্কার are

কাকতালীয়ভাবে আমি এই সম্পর্কে শুধুমাত্র একটি লিস্প ক্লাসে শিখেছি এবং এটি জাভাস্ক্রিপ্টে প্রয়োগ করার ক্ষেত্রেও ঘটে।

আমি এই কোডটি ক্রোমের কনসোলে চালিয়েছি।

// JavaScript               Equivalent Lisp
var x = 5;                //(setf x 5)
console.debug(x);         //(print x)
function print_x(){       //(defun print-x ()
    console.debug(x);     //    (print x)
}                         //)
(function(){              //(let
    var x = 10;           //    ((x 10))
    console.debug(x);     //    (print x)
    print_x();            //    (print-x)
})();                     //)

আউটপুট:

5
10
5

3

জাভাস্ক্রিপ্টে একটি লেজিকাল স্কোপ মানে যে কোনও ফাংশনের বাইরে সংজ্ঞায়িত একটি ভেরিয়েবল ভেরিয়েবল ঘোষণার পরে সংজ্ঞায়িত অন্য ফাংশনের অভ্যন্তরে অ্যাক্সেসযোগ্য হতে পারে। তবে বিপরীতটি সত্য নয়; একটি ফাংশনের ভিতরে সংজ্ঞায়িত ভেরিয়েবলগুলি সেই ফাংশনের বাইরে অ্যাক্সেসযোগ্য হবে না।

এই ধারণাটি জাভাস্ক্রিপ্টে ক্লোজারগুলিতে ভারী ব্যবহৃত হয়।

ধরা যাক আমাদের নীচের কোড রয়েছে।

var x = 2;
var add = function() {
    var y = 1;
    return x + y;
};

এখন, আপনি যখন অ্যাড () -> কল করবেন তখন এটি 3 মুদ্রণ করবে।

সুতরাং, অ্যাড () ফাংশনটি গ্লোবাল ভেরিয়েবল অ্যাক্সেস করছে xযা পদ্ধতি ফাংশন অ্যাডের আগে সংজ্ঞায়িত হয়েছে। এটি জাভাস্ক্রিপ্টে লেক্সিকাল স্কোপিংয়ের কারণে বলা হয়।


বিবেচনা করুন যে কোড স্নিপেটটি গতিশীল-স্কোপযুক্ত ভাষার জন্য ছিল। add()প্রদত্ত কোড স্নিপেটের সাথে সাথেই যদি ফাংশনটি তত্ক্ষণাত ডাকা হয় তবে এটি 3 প্রিন্টও করে। সুতরাং উদাহরণস্বরূপ কোডটি লেক্সিকাল স্কোপিংয়ের অর্থ কী তা বোঝাতে সত্যিই সহায়তা করে না। কোডে লেজিকাল স্কোপিং দেখানোর জন্য সত্যই একটি পাল্টা উদাহরণ বা কোডটির অন্যান্য সম্ভাব্য ব্যাখ্যার কমপক্ষে ব্যাখ্যা দরকার।
সি পার্কিনস

2

লেজিকাল স্কোপটি এক্সিকিউশন স্ট্যাকের বর্তমান অবস্থান থেকে দৃশ্যমান শনাক্তকারীদের (যেমন, ভেরিয়েবল, ফাংশন, ইত্যাদি) এর অভিধানকে বোঝায়।

- global execution context
    - foo
    - bar
    - function1 execution context
        - foo2
        - bar2
        - function2 execution context
            - foo3
            - bar3

fooএবং barসর্বদা উপলব্ধ শনাক্তকারীদের অভিধানের মধ্যে থাকে কারণ তারা বিশ্বব্যাপী।

যখন function1মৃত্যুদন্ড কার্যকর করা হয়, এটি একটি শব্দকোষ অ্যাক্সেস আছে foo2, bar2, foo, এবং bar

যখন function2মৃত্যুদন্ড কার্যকর করা হয়, এটি একটি শব্দকোষ অ্যাক্সেস আছে foo3, bar3, foo2, bar2, foo, এবং bar

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

অবশেষে, এ কারণেই কোনও নেস্টেড এক্সিকিউশন প্রসঙ্গটি তার পূর্বপুরুষদের সম্পাদন প্রসঙ্গে সর্বদা অ্যাক্সেস করতে পারে এবং সুতরাং এটির কেন শনাক্তকারীদের বৃহত্তর অভিধানে অ্যাক্সেস থাকতে পারে।

দেখা:

উপরোক্ত সংজ্ঞাটি সরলকরণে সহায়তার জন্য @ রবার3rd কে বিশেষ ধন্যবাদ


1

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

ব্যাখ্যার মধ্যে তিনটি বিষয়ের উপর নজর রাখা জড়িত:

  1. স্টেট - যথা, ভেরিয়েবল এবং রেফারেন্সযুক্ত মেমরি লোকেশন হ্যাপ এবং স্ট্যাকের উপর।

  2. এই রাজ্যে অপারেশন - যথা আপনার প্রোগ্রামে কোডের প্রতিটি লাইন

  3. যে পরিবেশে প্রদত্ত অপারেশনটি চালিত হয় - যথা, কোনও অপারেশনে রাষ্ট্রের অভিক্ষেপ ।

একটি দোভাষী একটি প্রোগ্রামের কোডের প্রথম লাইনে শুরু করে, তার পরিবেশের গণনা করে, সেই পরিবেশে লাইনটি চালান এবং প্রোগ্রামের স্থিতিতে এর প্রভাব ক্যাপচার করেন। এরপরে কোডটির পরবর্তী লাইনটি কার্যকর করতে প্রোগ্রামটির নিয়ন্ত্রণ প্রবাহ অনুসরণ করে এবং প্রোগ্রাম শেষ না হওয়া পর্যন্ত প্রক্রিয়াটি পুনরাবৃত্তি করে।

যে কোনও অপারেশনের জন্য আপনি পরিবেশকে কীভাবে গণনা করছেন তা হ'ল প্রোগ্রামিং ভাষা দ্বারা নির্ধারিত নিয়মের একটি আনুষ্ঠানিক সেট। "বাইন্ডিং" শব্দটি প্রায়শই প্রোগ্রামের সামগ্রিক অবস্থার ম্যাপিংটিকে পরিবেশের একটি মান হিসাবে বর্ণনা করতে ব্যবহৃত হয়। নোট করুন যে "সামগ্রিক রাষ্ট্র" দ্বারা আমরা বিশ্বব্যাপী রাষ্ট্রকে বোঝায় না, বরং মৃত্যুদন্ড কার্যকর করার যে কোনও সময়ে প্রতিটি পৌঁছনীয় সংজ্ঞাটির যোগফল)।

এটি সেই কাঠামো যেখানে স্কোপিং সমস্যা সংজ্ঞায়িত করা হয়। এখন আমাদের বিকল্পগুলি কি তার পরবর্তী অংশে।

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

এটি গতিশীল স্কোপিংয়ের সংক্ষিপ্তসার , এর মধ্যে যে কোনও পরিবেশে যে পরিবেশটি চালিত হয় তা প্রোগ্রামের রাজ্যটির সাথে আবদ্ধ হয় যার প্রয়োগের প্রসঙ্গ দ্বারা নির্ধারিত হয়।

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

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


0

প্রাচীন প্রশ্ন, তবে এখানে এটি গ্রহণ করা আমার।

লেক্সিকাল (স্ট্যাটিক) স্কোপটি উত্স কোডের একটি ভেরিয়েবলের সুযোগকে বোঝায় ।

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

বিষয়টি বর্ণনা করার জন্য:

var a='apple';

function doit() {
    var a='aardvark';
    return function() {
        alert(a);
    }
}

var test=doit();
test();

উদাহরণস্বরূপ, চলকটি aবিশ্বব্যাপী সংজ্ঞায়িত করা হয় তবে ফাংশনটিতে ছায়া গোছানো হয় doit()। এই ফাংশনটি আবার একটি ফাংশন প্রদান করে যা আপনি দেখতে পাচ্ছেন, aতার নিজস্ব ক্ষেত্রের বাইরে চলকটির উপর নির্ভর করে ।

আপনি যদি এটি চালান, আপনি দেখতে পাবেন যে ব্যবহৃত মানটি এটি aardvarkনয় apple, যদিও এটি test()ফাংশনের আওতায় রয়েছে, মূল ফাংশনের লেজিকাল স্কোপে নেই। এটি হ'ল ব্যবহৃত স্কোপটি হ'ল সুযোগটি যেমন উত্স কোডে প্রদর্শিত হয়, যেখানে কর্মটি আসলে ব্যবহৃত হয় এমন সুযোগ নয়।

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

var a='apple',b='banana';

function init() {
  var a='aardvark',b='bandicoot';
  document.querySelector('button#a').onclick=function(event) {
    alert(a);
  }
  document.querySelector('button#b').onclick=doB;
}

function doB(event) {
  alert(b);
}

init();
<button id="a">A</button>
<button id="b">B</button>

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

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


-1

আমি সাধারণত উদাহরণ দিয়ে শিখি, এবং এখানে একটি সামান্য কিছু:

const lives = 0;

function catCircus () {
    this.lives = 1;
    const lives = 2;

    const cat1 = {
        lives: 5,
        jumps: () => {
            console.log(this.lives);
        }
    };
    cat1.jumps(); // 1
    console.log(cat1); // { lives: 5, jumps: [Function: jumps] }

    const cat2 = {
        lives: 5,
        jumps: () => {
            console.log(lives);
        }
    };
    cat2.jumps(); // 2
    console.log(cat2); // { lives: 5, jumps: [Function: jumps] }

    const cat3 = {
        lives: 5,
        jumps: () => {
            const lives = 3;
            console.log(lives);
        }
    };
    cat3.jumps(); // 3
    console.log(cat3); // { lives: 5, jumps: [Function: jumps] }

    const cat4 = {
        lives: 5,
        jumps: function () {
            console.log(lives);
        }
    };
    cat4.jumps(); // 2
    console.log(cat4); // { lives: 5, jumps: [Function: jumps] }

    const cat5 = {
        lives: 5,
        jumps: function () {
            var lives = 4;
            console.log(lives);
        }
    };
    cat5.jumps(); // 4
    console.log(cat5); // { lives: 5, jumps: [Function: jumps] }

    const cat6 = {
        lives: 5,
        jumps: function () {
            console.log(this.lives);
        }
    };
    cat6.jumps(); // 5
    console.log(cat6); // { lives: 5, jumps: [Function: jumps] }

    const cat7 = {
        lives: 5,
        jumps: function thrownOutOfWindow () {
            console.log(this.lives);
        }
    };
    cat7.jumps(); // 5
    console.log(cat7); // { lives: 5, jumps: [Function: thrownOutOfWindow] }
}

catCircus();

-1

এই বিষয়টি অন্তর্নির্মিত bindফাংশনটির সাথে দৃ strongly়ভাবে সম্পর্কিত এবং ECMAScript 6 তীর ফাংশনে প্রবর্তিত । এটি সত্যিই বিরক্তিকর ছিল, কারণ প্রতিটি নতুন "শ্রেণি" (ফাংশন আসলে) পদ্ধতির জন্য আমরা ব্যবহার করতে চেয়েছিলাম, bindসুযোগটির অ্যাক্সেস পাওয়ার জন্য আমাদের এটি করতে হয়েছিল।

জাভাস্ক্রিপ্ট ডিফল্টরূপে তার সুযোগ সেট করেনি thisফাংশন উপর (এটা সেট করেনি প্রসঙ্গ উপর this)। ডিফল্টরূপে আপনি কোন প্রসঙ্গে থাকতে চান তা স্পষ্ট করে বলতে হবে।

তীর ফাংশন স্বয়ংক্রিয়ভাবে তথাকথিত পরার আভিধানিক সুযোগ (তার ধারণকারী ব্লক মধ্যে পরিবর্তনশীল সংজ্ঞা এক্সেস আছে)। তীর ফাংশনগুলি ব্যবহার thisকরার সময় এটি স্বয়ংক্রিয়ভাবে সেই স্থানে আবদ্ধ হয় যেখানে প্রথম স্থানে তীর ফাংশনটি সংজ্ঞায়িত করা হয়েছিল, এবং এই তীর ফাংশনগুলির প্রসঙ্গটি এটির সাথে থাকা ব্লক।

নীচের সহজ উদাহরণগুলিতে এটি বাস্তবে কীভাবে কাজ করে তা দেখুন।

তীর ফাংশনগুলির পূর্বে (ডিফল্টরূপে কোনও যৌক্তিক সুযোগ নেই):

const programming = {
  language: "JavaScript",
  getLanguage: function() {
    return this.language;
  }
}

const globalScope = programming.getLanguage;
console.log(globalScope()); // Output: undefined

const localScope = programming.getLanguage.bind(programming);
console.log(localScope()); // Output: "JavaScript"

তীর ফাংশন সহ (ডিফল্টরূপে লেজিকাল স্কোপ):

const programming = {
  language: "JavaScript",
  getLanguage: function() {
    return this.language;
  }
}

const arrowFunction = () => {
    console.log(programming.getLanguage());
}

arrowFunction(); // Output: "JavaScript"
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.