代码之家  ›  专栏  ›  技术社区  ›  Ian Baget

获取作用域中的所有变量

  •  162
  • Ian Baget  · 技术社区  · 16 年前

    有没有一种方法可以获取当前在javascript范围内的所有变量?

    9 回复  |  直到 9 年前
        1
  •  74
  •   Daniel Wolf deepee1    10 年前

    不,“in scope”变量由“scope chain”确定,不能通过编程方式访问。

    有关详细信息(相当多),请查看ecmascript(javascript)规范。 Here's a link 到您可以下载规范规范规范(PDF)的官方页面,以及 here's one 官方的,可链接的HTML版本。

    根据您对Camsoft的评论进行更新

    变量 在范围内 因为事件函数由定义事件函数的位置决定,而不是由它们如何调用。 但是 ,您可以通过 this 根据Kennytm所指出的做一些事情来争论( for (var propName in ____) )因为这将告诉您在提供给您的各种对象上有什么可用性( 如果你不确定他们给你什么样的论据,你可以通过 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的dev工具这样的调试器(即使您通常不使用chrome进行开发),或者 Firebug (即使您通常不使用火狐进行开发),或者在Opera上使用蜻蜓,或者在IE上使用“F12开发工具”,并阅读它们提供给您的任何javascript文件。打他们的头找合适的医生。-)

        2
  •  76
  •   iman    11 年前

    尽管每个人都回答 我知道“不”是正确的答案,但是如果你真的需要 局部变量 对于一个函数,有一个限制的方法。

    考虑这个函数:

    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);
        };
    }
    

    您只需访问 X 而不是 Y . 但是你仍然可以使用 呼叫者 (arguments.callee.caller.caller.caller)在循环中查找调用函数的局部变量。如果您有所有本地变量名,那么 范围变量 . 通过变量名,您可以使用简单的eval访问值。

        3
  •  31
  •   Justin Johnson    16 年前

    是和否。几乎在所有情况下都是“不”。是的,”但是只有在有限的方式下,如果你想检查全局范围的话。举个例子:

    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
    

    所以可以列出当前作用域中的一些变量,但是 它不可靠、简洁、高效或不易接近。

    一个更好的问题是 为什么要知道范围中有哪些变量?

        4
  •  16
  •   Christian C. Salvadó    16 年前

    你不能。

    变量、函数声明的标识符和函数代码的参数作为 Variable Object ,不可访问。

    另请参见:

        5
  •  15
  •   Community Mohan Dere    9 年前

    在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);

    代理声明拥有内部引用的所有标识符 具有 ,因此变量赋值存储在目标中。对于查找,代理从代理目标或全局对象(而不是父范围)中检索值。 let const 不包括变量。

    受到启发 this answer 通过 Bergi .

        6
  •  7
  •   rafaelcastrocouto    14 年前

    大家都注意到了:你不能。 但您可以创建一个对象并将您声明的每个var分配给该对象。 这样您就可以轻松地查看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
    
        7
  •  7
  •   Timothy Perez    11 年前

    在特定范围内访问var的最简单方法

    1. 打开开发人员工具资源(在chrome中)
    2. 使用可以访问该范围的函数打开文件(提示cmd/ctrl+p以查找文件)
    3. 在函数内部设置断点并运行代码
    4. 当它在断点处停止时,您可以通过控制台(或scope var窗口)访问scope var。

    注: 你想对未缩小的JS做这个。

    显示所有非私有变量的最简单方法

    1. 打开控制台(镀铬)
    2. 类型: 这个窗口
    3. 命中进入

    现在,您将看到一个对象树,您可以用所有声明的对象展开它。

        8
  •  3
  •   David Meister    10 年前

    如果只想手动检查变量以帮助调试,只需启动调试器:

    debugger;

    直接进入浏览器控制台。

        9
  •  -3
  •   mathheadinclouds    9 年前
    1. 从一开始就有人以任何方式或方式书写或打字过的每一个单词的列表(绝对是数学意义上的有限列表)。

    2. 把它们全部放在一个大数组中,通过在开发控制台中再次键入它们(作为字符串,这样就不会在这里引发错误)。

    3. 创建新数组,并在有限列表上执行循环,如果由于引用错误(使用eval“unstring”,因为如果不在范围内,则不在catch中结束try/catch,则将其推入新数组。

    4. 我收回它。我在第1点中提到的列表不够大。他们可以通过window[randomlyGeneratedString]=创建变量。在合理可行的时间范围内(比如,计算机发明以来的时间),更好地循环任何计算机程序都可以生成的所有字符串。


    好吧,说真的,你可以这样做,用1)在整个代码库上运行esprima.parse,在树上遍历名为“identifier”的东西,并存储它们的“name”得到什么。但是,您将错过正在创建的变量,如窗口[“file”+i]=blah中所示,请参见4。