Getting All Variables In Scope
有没有一种方法可以获取当前在javascript范围内的所有变量?
虽然每个人都回答"不",我知道"不"是正确的答案,但如果你真的需要得到一个函数的局部变量,有一个限制的方法。
考虑这个函数:
1 2 3 4 | var f = function() { var x = 0; console.log(x); }; |
您可以将函数转换为字符串:
1 | var s = f + ''; |
号
您将得到作为字符串的函数源
1 2 3 4 | 'function () { var x = 0; console.log(x); }' |
现在您可以使用像esprima这样的解析器来解析函数代码和查找局部变量声明。
1 2 3 4 5 6 7 | var s = 'function () { var x = 0; console.log(x); }'; s = s.slice(12); // to remove"function ()" var esprima = require('esprima'); var result = esprima.parse(s); |
。
查找对象时使用:
1 | obj.type =="VariableDeclaration" |
结果(我删除了下面的EDOCX1[0]):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | { "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中测试过这个。
但是这个方法的问题是你只需要在函数本身中定义变量。例如,对于这一个:
1 2 3 4 5 6 7 | 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的评论进行更新
事件函数作用域中的变量由定义事件函数的位置决定,而不是由它们如何调用。但是,您可以通过
因此,除了在范围内定义函数的位置之外,您还可以通过执行以下操作找到其他可用的方法:
1 2 3 4 5 6 7 8 9 10 11 12 | 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的dev工具(即使您通常不使用chrome进行开发)或firebug(即使您通常不使用firefox进行开发),或者在opera上使用dragonfly,或者在ie上使用f12开发人员工具,并阅读他们提供给您的任何javascript文件。打他们的头找合适的医生。-)
是和否。几乎在所有情况下都是"不"。是的,"但是只有在有限的方式下,如果你想检查全局范围的话。举个例子:
1 2 3 4 5 | var a = 1, b = 2, c = 3; for ( var i in window ) { console.log(i, typeof window[i], window[i]); } |
号
在150多件其他事情中,其输出如下:
1 2 3 4 5 6 7 8 9 10 | 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 |
因此,在当前范围内列出一些变量是可能的,但它不可靠、简洁、高效或容易访问。
一个更好的问题是,为什么要知道范围中有哪些变量?
在ecmascript 6中,通过使用代理对象将代码包装在
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | 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); |
代理声明拥有
灵感来自于伯吉的回答。
你不能。
变量、函数声明的标识符和函数代码的参数被绑定为变量对象的属性,这是不可访问的。
另请参见:
- 范围链和标识符解析
在特定范围内访问var的最简单方法
注意:您要针对未缩小的JS执行此操作。
显示所有非私有变量的最简单方法现在,您将看到一个对象树,您可以用所有声明的对象展开它。
大家都注意到了:你不能。但您可以创建一个对象并将您声明的每个var分配给该对象。这样您就可以轻松地查看vars:
1 2 3 4 5 6 7 8 9 10 | 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 |
。
如果只想手动检查变量以帮助调试,只需启动调试器:
江户十一〔一〕号
直接进入浏览器控制台。
从一开始就有人以任何方式或方式书写或打字过的每一个单词的列表(绝对是数学意义上的有限列表)。
通过在开发人员控制台中再次输入它们(作为字符串),将它们全部放入一个大数组中,这样就不会在这里引发错误。
创建新数组,并在有限列表上执行循环,如果由于引用错误(使用eval"unstring",因为如果不在范围内,您希望在此处出现错误),则在try/catch(仅在try中执行)未在catch中结束时将其推入新数组。
我收回它。我在第1点提到的列表不够大。他们可以通过window[randomlyGeneratedString]=创建变量。更好的循环所有的字符串,这些字符串可以由停在合理可行的时间范围内的任何计算机程序生成,例如,自计算机发明以来的时间。
好吧,说真的,你可以这样做,用1)在整个代码库上运行esprima.parse,在树上遍历名为"identifier"的东西,并存储它们的"name"得到什么。但是,您将错过正在创建的变量,如窗口["file"+i]=blah中所示,请参见4。