[解決済み] Chromeデバッガーが閉じたローカル変数を未定義と判断するのはなぜですか?
質問
このコードで
function baz() {
var x = "foo";
function bar() {
debugger;
};
bar();
}
baz();
このような予期せぬ結果になってしまいます。
コードを変更すると
function baz() {
var x = "foo";
function bar() {
x;
debugger;
};
bar();
}
期待通りの結果が得られます。
また、もし
eval
に何を渡すかは問題ではありません)。
eval
).
一方、Firefoxの開発ツールでは、どちらの状況でも期待通りの動作が得られます。
デバッガーの挙動がFirefoxより不便なChromeはどうしたんだ?Version 41.0.2272.43 beta (64-bit)までは、以前からこの挙動を確認しています。
クロームのjavascriptエンジンが、可能な限り関数をフラットにしているのでしょうか?
面白いことに、2つ目の変数に
は
内部関数で参照される
x
変数は未定義のままです。
対話型デバッガを使用する場合、スコープや変数定義に癖があることは理解していますが、言語仕様に基づき、これらの癖に対する "ベスト"ソリューションがあるはずだと思われます。そこで、Chrome が Firefox よりもさらに最適化していることが原因なのかどうか、非常に気になります。また、これらの最適化を開発中に簡単に無効にできるかどうかも気になります(開発ツールを開いているときに無効にすべきなのかもしれませんね)。
また、ブレークポイントを使っても再現できるのは
debugger
ステートメントを使用します。
どのように解決するのですか?
V8を発見 問題報告 という質問に対して、まさにその通りです。
さて、そのレポートに書かれていることを要約すると...v8は、関数にローカルな変数をスタックに格納できます。
または
ヒープ上に存在するコンテキストオブジェクトの中にあります。関数がそれを参照する内部関数を含んでいない限り、スタック上にローカル変数を確保します。
最適化である
. もし
任意の
内部関数がローカル変数を参照している場合、この変数はコンテキストオブジェクトに置かれます (つまり、スタック上ではなくヒープ上に置かれます)。の場合は
eval
は特殊で、内部関数からまったく呼び出されない場合です。
すべて
のローカル変数がコンテキストオブジェクトに置かれます。
コンテキストオブジェクトが必要な理由は、一般的に外側の関数から内側の関数を返すと、外側の関数が実行されている間に存在したスタックが使えなくなるからです。そのため、内部関数がアクセスするものはすべて外部関数から生き残り、スタック上ではなくヒープ上に存在しなければなりません。
デバッガはスタック上にある変数を検査することができません。デバッグ時に発生する問題については、あるプロジェクトメンバーが とは :
私が思いついた唯一の解決策は、devtools がオンのときはいつでも、すべてのコードをデオプトし、強制的なコンテキスト割り当てで再コンパイルすることです。しかし、それではdevtoolsが有効なときにパフォーマンスが劇的に低下してしまいます。
以下は、"if any inner function refers to the variable, put it in a context object"の一例です。これを実行すると、次のようにアクセスできるようになります。
x
での
debugger
ステートメントを使用しているにもかかわらず
x
が使われているのは
foo
関数を使用します。
を呼び出すことはありません。
!
function baz() {
var x = "x value";
var z = "z value";
function foo () {
console.log(x);
}
function bar() {
debugger;
};
bar();
}
baz();
関連
-
Vueの一般的な組み込みディレクティブの説明
-
[解決済み】TypeScript-のAngular Frameworkエラー - "exportAsがngFormに設定されたディレクティブはありません"
-
[解決済み] なぜGoogleはJSONレスポンスにwhile(1);を前置するのでしょうか?
-
[解決済み] 私のJavaScriptコードは "No 'Access-Control-Allow-Origin' header is present on requested resource "というエラーを受け取りますが、Postmanはそうならないのはなぜですか?
-
[解決済み] 変数が「未定義」または「NULL」であるかどうかを判断するにはどうすればよいですか?
-
[解決済み] なぜ ++[[]][+[] +[+[]] は "10" という文字列を返すのでしょうか?
-
[解決済み] クロームデバッガ / DevToolsパネルで画面をフリーズさせて、ポップオーバーを検査する?
-
[解決済み] 「Chromeデバッガで「注意:暫定的なヘッダが表示されます。
-
[解決済み] Google ChromeでJavaScriptデバッガーを起動する方法を教えてください。
-
[解決済み】Chrome Developer Consoleで奇妙なエラー - リソースの読み込みに失敗しました: net::ERR_CACHE_MISS
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
要素ツリー制御によるvueTreeテーブル
-
jQueryのコピーオブジェクトの説明
-
Vueにシンプルなメモ帳機能を実装
-
vueはopenlayersを使用してスカイマップとガオードマップをロードする
-
vueにおけるv-forループオブジェクトのプロパティ
-
vueが定義するプライベートフィルタと基本的な使い方
-
VUEグローバルフィルターの概念と留意点、基本的な使い方
-
[解決済み】JavaScriptの配列でforEachが関数でない不具合
-
[解決済み】ERROR エラーです。スイッチのname属性が指定されていないフォームコントロールの値アクセッサがない
-
フロントエンド null のプロパティ 'disabled' を読み取れない 問題が解決された