現在JavaScriptのスコープ内にあるすべての変数を取得する方法はありますか?
for (v in this) alert(v);。ただし、すべてのグローバルが列挙可能であるとは限りません。列挙できないもののリストを取得する標準的な方法は知りません。
this、argumentsパラメータおよびスコープを囲んで定義されているすべての変数を。
現在JavaScriptのスコープ内にあるすべての変数を取得する方法はありますか?
for (v in this) alert(v);。ただし、すべてのグローバルが列挙可能であるとは限りません。列挙できないもののリストを取得する標準的な方法は知りません。
this、argumentsパラメータおよびスコープを囲んで定義されているすべての変数を。
回答:
いいえ。「スコープ内」変数は「スコープチェーン」によって決定され、プログラムからはアクセスできません。
詳細(かなりの量)については、ECMAScript(JavaScript)仕様を確認してください。ここでは、リンクだあなたは標準的な仕様(PDF)をダウンロードすることができ、公式ページには、とここで一つだ公式、リンク可能なHTMLバージョンに。
Camsoftへのコメントに基づいて更新
イベント関数のスコープ内の変数は、イベント関数の呼び出し方法ではなく、イベント関数を定義する場所によって決まります。しかし、thisKennyTMが指摘したこと(for (var propName in ____))に沿って何かを行うことで、関数や引数を介して利用できるものに関する有用な情報を見つけることができます()は、提供されているさまざまなオブジェクトで利用できるもの(thisおよび引数、それらがあなたに与える引数がわからない場合はarguments、すべての関数に対して暗黙的に定義されている変数を介して調べることができます)。
したがって、関数を定義する場所が原因で範囲内にあるものに加えて、他の方法で他に何が利用できるかを調べるには、次のようにします。
var n, arg, name;
alert("typeof this = " + typeof this);
for (name in this) {
alert("this[" + name + "]=" + this[name]);
}
for (n = 0; n < arguments.length; ++n) {
arg = arguments[n];
alert("typeof arguments[" + n + "] = " + typeof arg);
for (name in arg) {
alert("arguments[" + n + "][" + name + "]=" + arg[name]);
}
}
(これを拡張すると、さらに役立つ情報を取得できます。)
その代わりに、おそらく、Chromeの開発ツール(通常、開発にChromeを使用しない場合でも)またはFirebug(通常、Firefoxを開発に使用しない場合でも)のようなデバッガー、またはOpera上のDragonflyを使用します、またはIEの「F12 Developer Tools」。そして、それらが提供するJavaScriptファイルを読み通してください。そして、適切なドキュメントを取得するために頭を打ってください。:-)
誰もが「いいえ」と答え、私は「いいえ」が正しい答えであることを知っていますが、本当に関数のローカル変数を取得する必要がある場合、制限された方法があります。
この関数を考えてみましょう:
var f = function() {
var x = 0;
console.log(x);
};
関数を文字列に変換できます:
var s = f + '';
関数のソースを文字列として取得します
'function () {\nvar x = 0;\nconsole.log(x);\n}'
今、あなたは次のようにパーサーを使用することができますesprima機能コードを解析し、ローカル変数の宣言を見つけること。
var s = 'function () {\nvar x = 0;\nconsole.log(x);\n}';
s = s.slice(12); // to remove "function () "
var esprima = require('esprima');
var result = esprima.parse(s);
とオブジェクトを見つける:
obj.type == "VariableDeclaration"
結果(私はconsole.log(x)以下を削除しました):
{
"type": "Program",
"body": [
{
"type": "VariableDeclaration",
"declarations": [
{
"type": "VariableDeclarator",
"id": {
"type": "Identifier",
"name": "x"
},
"init": {
"type": "Literal",
"value": 0,
"raw": "0"
}
}
],
"kind": "var"
}
]
}
私はこれをChrome、Firefox、Nodeでテストしました。
しかし、この方法の問題は、関数自体に変数が定義されていることです。たとえば、この場合:
var g = function() {
var y = 0;
var f = function() {
var x = 0;
console.log(x);
};
}
yではなく、xにアクセスできます。ただし、ループ内で呼び出し元のチェーン(arguments.callee.caller.caller.caller)を使用して、呼び出し元関数のローカル変数を見つけることができます。すべてのローカル変数名があり、スコープ変数がある場合。変数名を使用すると、単純なevalで値にアクセスできます。
function getCounter(start){ return function(){ start ++; return start; } } var counter = getCounter(1); var startInClosure = eval.call(counter, 'this.start;'); console.log(startInClosure);それは印刷しundefined、私はそれが2でなければなりません期待しながら
はいといいえ。ほとんどすべての状況で「いいえ」。「はい」。ただし、グローバルスコープを確認する場合に限られます。次の例を見てください。
var a = 1, b = 2, c = 3;
for ( var i in window ) {
console.log(i, typeof window[i], window[i]);
}
150以上の中で、以下を出力します。
getInterface function getInterface()
i string i // <- there it is!
c number 3
b number 2
a number 1 // <- and another
_firebug object Object firebug=1.4.5 element=div#_firebugConsole
"Firebug command line does not support '$0'"
"Firebug command line does not support '$1'"
_FirebugCommandLine object Object
hasDuplicate boolean false
したがって、現在のスコープ内のいくつかの変数をリストすることは可能ですが、信頼性が高く、簡潔で、効率的で、簡単にアクセスできるわけではありません。
より良い質問は、なぜスコープ内にある変数を知りたいのですか?
for ( var i in window ) { if (window.hasOwnProperty(i)) { console.log(i, window[i]); }}。これにより、少なくとも継承されたプロパティが削減され、変数は他の約50のプロパティに含まれるようになります。
ECMAScript 6では、withステートメント内のコードをプロキシオブジェクトでラップすることで、多かれ少なかれ可能です。非厳密モードが必要であり、これは悪い習慣であることに注意してください。
function storeVars(target) {
return new Proxy(target, {
has(target, prop) { return true; },
get(target, prop) { return (prop in target ? target : window)[prop]; }
});
}
var vars = {}; // Outer variable, not stored.
with(storeVars(vars)) {
var a = 1; // Stored in vars
var b = 2; // Stored in vars
(function() {
var c = 3; // Inner variable, not stored.
})();
}
console.log(vars);
プロキシは、内部withで参照されるすべての識別子を所有していると主張しているため、変数の割り当てはターゲットに保存されます。ルックアップの場合、プロキシはプロキシターゲットまたはグローバルオブジェクト(親スコープではない)から値を取得します。letそしてconst変数が含まれていません。
withステートメントを使用してチェーンに他のオブジェクトを挿入できます)。
注:縮小化されていないjsに対してこれを行う必要があります。
これで、宣言されたすべてのオブジェクトで展開できるオブジェクトツリーが表示されます。
誰もが気づいたように、できません。しかし、objを作成し、宣言したすべてのvarをそのobjに割り当てることができます。そうすれば、変数を簡単にチェックアウトできます。
var v = {}; //put everything here
var f = function(a, b){//do something
}; v.f = f; //make's easy to debug
var a = [1,2,3];
v.a = a;
var x = 'x';
v.x = x; //so on...
console.log(v); //it's all there
console.log(window); jsfiddle.net/4x3Tx
私が作っフィドル(基本的に)イマンによって概説アイデアの上に実装します。これは、2番目のipsumにマウスを置いたときの様子です。return ipsum*ipsum - ...
スコープ内の変数は、宣言された場所で強調表示されます(スコープごとに異なる色で)。lorem赤い境界とする影可変である(スコープではないが、さらに木ダウン他のLoremのが存在しない場合範囲にあります。)
私はesprimaライブラリーを使用してJavaScriptを解析し、estraverse、escodegen、escope(esprimaの上にあるユーティリティー・ライブラリー)を使用しています。「重いリフティング」はすべてこれらのライブラリーによって行われます(もちろん、esprima自体が最も複雑です)。
使い方
ast = esprima.parse(sourceString, {range: true, sourceType: 'script'});
抽象構文木を作成します。そして、
analysis = escope.analyze(ast);
プログラム内のすべてのスコープに関する情報をカプセル化する複雑なデータ構造を生成します。残りは、その分析オブジェクト(および抽象構文ツリー自体)にエンコードされた情報を収集し、それからインタラクティブなカラーリングスキームを作成します。
したがって、正解は実際には「いいえ」ではなく「はい」です。「しかし」は大きな問題です。基本的に、JavaScriptでChromeブラウザー(およびそれは開発ツール)の重要な部分を書き直す必要があります。JavaScriptはチューリング完全言語ですので、もちろんそれは原則的に可能です。ソースコード全体を(文字列として)使用せずにすべてを実行し、それを使用して非常に複雑な処理を実行するのは不可能です。
デバッグに役立つように変数を手動で検査したい場合は、デバッガーを起動します。
debugger;
ブラウザコンソールに直接アクセスします。