是否有一种方法来获得目前在javascript范围内的所有变量?
当前回答
虽然每个人都回答“不”,我知道“不”是正确的答案,但如果你真的需要得到一个函数的局部变量,有一个有限的方法。
考虑这个函数:
var f = function() {
var x = 0;
console.log(x);
};
你可以把你的函数转换成一个字符串:
var s = f + '';
你会得到一个字符串形式的source of function
'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);
};
}
你只能得到x,而不是y。 但是仍然可以在循环中使用调用者链(arguments.callee.caller.caller.caller)来查找调用者函数的局部变量。如果你有所有的局部变量名,那么你就有了作用域变量。通过变量名,您可以通过简单的eval访问值。
其他回答
正如大家所注意到的:你不能。 但是你可以创建一个obj并将你声明的每个var赋值给那个obj。 这样你就可以很容易地检查你的vars:
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
在ECMAScript 6中,通过使用代理对象将代码包装在with语句中或多或少是可行的。注意,它需要非严格模式,这是不好的做法。
函数storeVars(目标){ 返回新的代理(目标,{ 有(目标,道具){返回true;}, Get(目标,道具){返回(道具在目标中?目标:窗口)[道具];} }); } Var vars = {};//外部变量,未存储。 (storeVars (var)) { Var a = 1;//存储在vars中 Var b = 2;//存储在vars中 (函数(){ Var c = 3;//内部变量,未存储 }) (); } console.log (var);
代理声称拥有with中引用的所有标识符,因此变量赋值存储在目标中。对于查找,代理从代理目标或全局对象(而不是父作用域)检索值。Let和const变量不包括在内。
灵感来自Bergi的回答。
我做了一个小提琴实现(本质上)以上的想法概述iman。下面是当你把鼠标放在第二个ipsum上,返回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浏览器(以及devtools)的重要部分。JavaScript是一种图灵完备语言,所以原则上这当然是可能的。不可能的是不使用源代码的全部(作为字符串),然后用它来做非常复杂的事情。
是也不是。几乎在任何情况下都说“不”。“是的”,但如果您想检查全局作用域,则只能以有限的方式进行。举个例子:
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
因此,可以在当前范围内列出一些变量,但它不可靠、不简洁、不高效或不容易访问。
一个更好的问题是,为什么要知道作用域内的变量是什么?
虽然每个人都回答“不”,我知道“不”是正确的答案,但如果你真的需要得到一个函数的局部变量,有一个有限的方法。
考虑这个函数:
var f = function() {
var x = 0;
console.log(x);
};
你可以把你的函数转换成一个字符串:
var s = f + '';
你会得到一个字符串形式的source of function
'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);
};
}
你只能得到x,而不是y。 但是仍然可以在循环中使用调用者链(arguments.callee.caller.caller.caller)来查找调用者函数的局部变量。如果你有所有的局部变量名,那么你就有了作用域变量。通过变量名,您可以通过简单的eval访问值。