ক্রোম ডিবাগার কেন ভাবেন যে বন্ধ স্থানীয় ভেরিয়েবল অপরিজ্ঞাত?


167

এই কোড সহ:

function baz() {
  var x = "foo";

  function bar() {
    debugger;
  };
  bar();
}
baz();

আমি এই অপ্রত্যাশিত ফলাফল পেয়েছি:

এখানে চিত্র বর্ণনা লিখুন

আমি যখন কোডটি পরিবর্তন করি:

function baz() {
  var x = "foo";

  function bar() {
    x;
    debugger;
  };
  bar();
}

আমি প্রত্যাশিত ফলাফল পেয়েছি:

এখানে চিত্র বর্ণনা লিখুন

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

এদিকে, ফায়ারফক্স ডিভাইস উভয় পরিস্থিতিতেই প্রত্যাশিত আচরণ দেয়।

ক্রোমের কী হল যে ডিবাগার ফায়ারফক্সের চেয়ে কম স্বাচ্ছন্দ্যে আচরণ করে? আমি কিছু সময়ের জন্য এই আচরণটি পর্যবেক্ষণ করেছি, সংস্করণ 41.0.2272.43 বিটা (64-বিট) পর্যন্ত to

এটি কি ক্রোমের জাভাস্ক্রিপ্ট ইঞ্জিন যখন এটি করতে পারে তখন ফাংশনগুলিকে "সমতল" করে?

উত্সাহের ব্যাপার হল যদি আমি একটি দ্বিতীয় পরিবর্তনশীল যে যোগ করা হয় ভেতরের ফাংশন উল্লেখ, xপরিবর্তনশীল এখনো অনির্দিষ্ট করা হয়।

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

এছাড়াও, আমি ব্রেকপয়েন্টের পাশাপাশি debuggerবিবৃতি দিয়ে এটি পুনরুত্পাদন করতে পারি ।


2
হতে পারে এটি আপনার জন্য আপনার ব্যবহারের বাইরে অ-ব্যবহৃত ভেরিয়েবলগুলি পেয়ে যাচ্ছে ...
ডান্ডাভিস

markle976 বলছে বলে মনে হয় debugger;লাইন আসলে ভেতর থেকে বলা হয় না bar। সুতরাং ডিবাগারে যখন বিরতি দেয় তখন স্ট্যাক ট্রেসটি দেখুন: স্ট্যাকট্রেসে barউল্লিখিত ফাংশনটি কি ? যদি আমি ঠিকই থাকি, তবে স্ট্যাকট্রেসকে বলা উচিত এটি it's নং লাইনে line, লাইন 5-তে দাঁড়িয়ে আছে
ডেভিড নিপ

আমি মনে করি না এটি ভি 8 সমতলকরণ কার্যক্রমে কিছু করার আছে। আমি মনে করি এটি কেবল একটি শিহরিত; আমি এটিকে একটি বাগও বলি কিনা জানি না। আমি মনে করি নীচে ডেভিডের উত্তরটি সার্থক করে তোলে।
মার্কেল 976


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

উত্তর:


149

আমি একটি ভি 8 ইস্যু রিপোর্ট পেয়েছি যা আপনি যা জিজ্ঞাসা করছেন তা সম্পর্কে অবিকল।

এখন, এই সমস্যাটির প্রতিবেদনে যা বলা হয়েছে তার সংক্ষিপ্ত বিবরণে ... v8 স্ট্যাকের কোনও ফাংশনে স্থানীয় যে ভেরিয়েবলগুলি সংরক্ষণ করতে পারে বা একটি "প্রসঙ্গ" অবজেক্টে যা গাদাতে থাকে। এটি স্ট্যাকের উপরে স্থানীয় ভেরিয়েবলগুলি এত দিন বরাদ্দ করবে যতক্ষণ ফাংশনে কোনও অভ্যন্তরীণ ফাংশন তাদের উল্লেখ করে না। এটি একটি অপ্টিমাইজেশন । যদি কোনও অভ্যন্তরীণ ফাংশন স্থানীয় ভেরিয়েবলকে বোঝায়, এই পরিবর্তনশীলটিকে একটি প্রসঙ্গ বস্তুতে স্থাপন করা হবে (অর্থাত্ স্ট্যাকের পরিবর্তে গাদা)। ক্ষেত্রে evalবিশেষ: যদি এটি একটি ভেতরের ফাংশন দ্বারা এ সব বলা হয়, সব স্থানীয় ভেরিয়েবল প্রসঙ্গ বস্তু রাখা হয়।

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

ডিবাগার স্ট্যাকের মধ্যে থাকা সমস্ত ভেরিয়েবলগুলি পরীক্ষা করতে পারে না। ডিবাগিংয়ের সময় যে সমস্যাটি দেখা দিয়েছে সে সম্পর্কে একজন প্রকল্প সদস্য বলেছেন :

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

এখানে "যদি কোনও অভ্যন্তরীণ ফাংশনটি ভেরিয়েবলকে বোঝায়, একটি প্রসঙ্গ বস্তুতে রাখুন" এর একটি উদাহরণ এখানে। আপনি চালাতে যদি এ আপনি অ্যাক্সেস করতে সক্ষম হবেন xdebuggerবিবৃতি যদিও xশুধুমাত্র ব্যবহার করা হয় fooফাংশন, যা কখনো বলা হয় !

function baz() {
  var x = "x value";
  var z = "z value";

  function foo () {
    console.log(x);
  }

  function bar() {
    debugger;
  };

  bar();
}
baz();

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

ডিবাগ করার সময় আমি আসলে এই সমস্যার মধ্যে পড়ে যাইনি তাই কোড ডিওপ্ট করার উপায়গুলি আমি অনুসন্ধান করি নি।
লুই

6
ইস্যুটির সর্বশেষ মন্তব্যটি বলেছে: ভি 8 কে এমন মোডে রেখে দেওয়া যেখানে জোর করে সমস্ত বিষয় বরাদ্দ করা সম্ভব, তবে আমি নিশ্চিত নই / ডিবাগল ইউআইয়ের মাধ্যমে ডিবাগিংয়ের খাতিরে কীভাবে / কখন এটি ট্রিগার করা যায় , আমি মাঝে মাঝে এটি করতে চাইতাম । আমি কিভাবে এই ধরনের মোড জোর করতে পারি?
সুমা

2
@ ব্যবহারকারী208769 সদৃশ হিসাবে বন্ধ করার সময়, আমরা ভবিষ্যতের পাঠকদের জন্য সবচেয়ে দরকারী প্রশ্নটির পক্ষে আছি। একাধিক কারণ রয়েছে যা কোন প্রশ্নটি সবচেয়ে কার্যকর তা নির্ধারণে সহায়তা করে: আপনার প্রশ্নের ঠিক 0 টি উত্তর পেয়েছে যখন এই একের একাধিক upvated উত্তর পেয়েছে। সুতরাং এই প্রশ্নটি দুজনের মধ্যে সবচেয়ে বেশি কার্যকর। কার্যকারিতা বেশিরভাগ সমান হলেই তারিখগুলি একটি নির্ধারক ফ্যাক্টর হয়।
লুই

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

30

@ লুইস পছন্দ করেছেন বলেছিলেন এটি ভি 8 অপটিমাইজেশনের কারণে ঘটেছে। আপনি কল স্ট্যাকটি ফ্রেমে ট্র্যাভার করতে পারেন যেখানে এই পরিবর্তনশীলটি দৃশ্যমান:

call1 call2

বা debuggerসঙ্গে প্রতিস্থাপন

eval('debugger');

eval বর্তমান খণ্ডটি ডিপ্ট করবে


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

ওহ ... এটা এমনকি clunkier হলুদ ব্যবহার করতে থাকার চেয়ে এর evalপ্রেক্ষাপটে অ্যাক্সেস পেতে ইডি উৎস জানালা: তুমি কি কোড মাধ্যমে পদক্ষেপ (যতক্ষণ না আপনি লাগাতে পারেন eval('debugger')। এতদুভয়ের মধ্যবর্তী সব কিছুর লাইন আপনি মাধ্যমে পদক্ষেপ চান)
Sigfried

দেখে মনে হয় যে এমন পরিস্থিতি রয়েছে যেখানে উপযুক্ত স্ট্যাক ফ্রেমে ট্র্যাভার করার পরেও কিছু পরিবর্তনশীল অদৃশ্য থাকে; আমার মতো কিছু আছে controllers.forEach(c => c.update())এবং গভীরতর কোথাও একটি ব্রেকপয়েন্টে আঘাত করে c.update()। আমি যদি তখন ফ্রেমটি নির্বাচিত করি যেখানে controllers.forEach()ডাকা হয়, controllersঅপরিজ্ঞাত হয় (তবে সেই ফ্রেমের সমস্ত কিছুই দৃশ্যমান হয়)। আমি একটি ন্যূনতম সংস্করণ দিয়ে পুনরুত্পাদন করতে পারিনি, আমি মনে করি জটিলতার কিছু প্রান্ত হতে পারে যা উত্তীর্ণ হতে হবে বা কিছু।
পিটারটি

@ পিটারটি যদি এটি <সংজ্ঞায়িত> হয় তবে আপনি ভুল জায়গায় আছেন বা somewhere deep inside c.update()আপনার কোডটি
অ্যাসিঙ্ক হয়

6

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


2
ধন্যবাদ। মূলত আমি এটি "ডিবাগার মিথ্যা" এর চেয়ে জাভাস্ক্রিপ্ট শুরুর দিকে আরও ভালভাবে ব্যাখ্যা করতে সক্ষম হতে চাই।
গ্যাবে কোপলি

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

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

2

বাহ, সত্যিই আকর্ষণীয়!

অন্যরা যেমন উল্লেখ করেছেন, এটি সম্পর্কিত বলে মনে হয় তবে এর সাথে scopeআরও বিশেষভাবে সম্পর্কিত debugger scope। যখন ইনজেকশন স্ক্রিপ্টটি বিকাশকারী সরঞ্জামগুলিতে মূল্যায়ন করা হয়, তখন এটি একটি নির্ধারণ করা হয় ScopeChain, যার ফলশ্রুতিতে কিছুটা কৌতূহল হয় (যেহেতু এটি পরিদর্শক / ডিবাগার স্কোপের সাথে আবদ্ধ)। আপনি যা পোস্ট করেছেন তার একটি বৈকল্পিকতা হ'ল:

(সম্পাদনা করুন - আসলে, আপনি এটি আপনার মূল প্রশ্নে উল্লেখ করেছেন, হাই, আমার খারাপ! )

function foo() {
  var x = "bat";
  var y = "man";

  function bar() {
    console.log(x); // logs "bat"

    debugger; // Attempting to access "y" throws the following
              // Uncaught ReferenceError: y is not defined
              // However, x is available in the scopeChain. Weird!
  }
  bar();
}
foo();

উচ্চাভিলাষী এবং / অথবা কৌতূহলের জন্য, কী ঘটছে তা দেখার জন্য উত্সটি (heh) খুঁজে বের করুন:

https://github.com/WebKit/webkit/tree/master/Source/JavaScriptCore/inspector https://github.com/WebKit/webkit/tree/master/Source/JavaScriptCore/debugger


0

আমার সন্দেহ হয় এটি ভেরিয়েবল এবং ফাংশন উত্তোলনের সাথে সম্পর্কিত। জাভাস্ক্রিপ্ট এখানে ফাংশন তারা সংজ্ঞায়িত করা হয় উপরের সব পরিবর্তনশীল এবং ফাংশন ঘোষণা এনেছে আরও তথ্য। Http://jamesallardice.com/explaining-function-and-variable-hoisting-in-javascript/

আমি বাজি ধরেছি যে ক্রোমটি ভেরিয়েবলের সাথে ব্রেক পয়েন্টটি কলকে সুযোগের জন্য অনুপলব্ধ বলে কল করছে কারণ ফাংশনে আর কিছুই নেই। এটি কাজ করে বলে মনে হচ্ছে:

function baz() {
  var x = "foo";

  function bar() {
    console.log(x); 
    debugger;
  };
  bar();
}

এটি যেমন করে:

function baz() {
  var x = "foo";

  function bar() {
    debugger;
    console.log(x);     
  };
  bar();
}

আশা করি এটি এবং / অথবা উপরের লিঙ্কটি সহায়তা করে। এগুলি আমার প্রিয় ধরণের এসও প্রশ্নগুলি, বিটিডাব্লু :)


ধন্যবাদ! :) আমি ভাবছি এফএফ আলাদাভাবে কী করে। বিকাশকারী হিসাবে আমার দৃষ্টিকোণ থেকে, এফএফের অভিজ্ঞতাটি বস্তুনিষ্ঠভাবে আরও ভাল ...
গ্যাবে কোপলি

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