有没有办法获取当前在 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.js 中对此进行了测试。
但是这种方法的问题在于你只是在函数本身中定义了变量。例如对于这个:
var g = function() {
var y = 0;
var f = function() {
var x = 0;
console.log(x);
};
}
您只能访问x而不是y。但是您仍然可以在循环中使用调用者链(arguments.callee.caller.caller.caller)来查找调用者函数的局部变量。如果您拥有所有局部变量名称,那么您就有了作用域变量。使用变量名称,您可以使用简单的 eval 访问值。
不可以。“作用域内”变量由“作用域链”确定,不能以编程方式访问。
有关详细信息(很多),请查看 ECMAScript (JavaScript) 规范。这里有一个链接到官方页面,您可以下载该规范的规范(PDF格式),并且这里有一个官方的,可链接的HTML版本。
根据您对 Camsoft 的评论进行更新
事件函数作用域内的变量取决于您定义事件函数的位置,而不是它们如何调用它。但是,通过this
按照 KennyTM 指出的内容 ( 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 开发人员工具”。并通读他们为您提供的任何 JavaScript 文件。并击败他们以获得适当的文档。:-)
在 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
变量不包括在内。
是和否。几乎在所有情况下都是“不”。“是”,但仅限于有限的方式,如果您想检查全局范围。以下面的例子为例:
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
所以可以列出当前作用域中的一些变量,但并不可靠、简洁、高效或易于访问。
一个更好的问题是为什么你想知道哪些变量在范围内?