8wDlpd.png
8wDFp9.png
8wDEOx.png
8wDMfH.png
8wDKte.png

获取范围内的所有变量

user25546454 1月前

103 0

有没有办法获取 javascript 中当前范围内的所有变量?

有没有办法获取 javascript 中当前范围内的所有变量?

帖子版权声明 1、本帖标题:获取范围内的所有变量
    本站网址:http://xjnalaquan.com/
2、本网站的资源部分来源于网络,如有侵权,请联系站长进行删除处理。
3、会员发帖仅代表会员个人观点,并不代表本站赞同其观点和对其真实性负责。
4、本站一律禁止以任何方式发布或转载任何违法的相关信息,访客发现请向站长举报
5、站长邮箱:yeweds@126.com 除非注明,本帖由user25546454在本站《list》版块原创发布, 转载请注明出处!
最新回复 (0)
  • 关于您对 Camsoft 的回答:这是一个完全不同的问题;我已更新我的答案以解决它。

  • sarh 1月前 0 只看Ta
    引用 3

    这只是一个一般性的问题,由于我正在使用一个文档不全的模糊 API,因此更具体的问题不会有太大帮助。

  • 这就是我怀念 Perl 符号表的原因。有计划将其添加到未来版本的 Javascript 中吗?

  • 不可以。“范围内”变量由“范围链”决定,无法通过编程访问。

    有关详细信息(相当多),请查看 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 文件。并仔细阅读它们以获取正确的文档。:-)

  • 附注一下,Google Chrome 有一个很出色的调试器,可以与 Firebug 媲美(并且还具有一些额外的功能)。

  • @Swivelgames:哦,我更喜欢 Chrome 的 Dev Tools,而不是 Firefox+Firebug。2010 年的时候它们还不够好。:-)

  • 虽然每个人的回答都是“”,而且我也知道“否”才是正确答案,但是如果你真的需要获取 局部变量 ,那么就有一种受限制的方法。

    考虑这个函数:

    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 在循环中 调用者 范围变量 。使用变量名,您可以通过简单的 eval 访问值。

  • 调用者的变量不一定是作用域变量。此外,作用域变量不一定在调用链中。当从定义/闭包作用域之外的调用者调用闭包函数时,已关闭的变量可能会被闭包函数引用(并且其变量根本无法从闭包主体中访问)。

  • 您能清楚地解释一下“一个简单的 eval”吗?我尝试使用下面的代码,但无法将变量困在 scope.function getCounter(start){ return function(){ start ++; return start; } } var counter = getCounter(1); var startInClosure = eval.call(counter, 'this.start;'); console.log(startInClosure); 它打印出未定义,而我预计它应该是 2。

  • @Pylipala 这里的问题是作用域内的变量无法从作用域外获取局部变量的值。这是不可能的,因为这是局部变量的定义,不应该从外部访问。关于您的代码,您的意思是上下文而不是作用域,但您没有将 start 放在上下文 (this) 中,因此您无法使用 this.start 读取它。请参阅此处:paste.ubuntu.com/11560449

  • 引用 12

    @iman 谢谢你的回答。我也猜想在 Javascript 端这是不可能的,所以我猜想在 v8 端这是否可行。我发现下面的问题链接准确地描述了我的问题。其中 Lasse Reichstein 说不行,但 mako-taco 说可以。我尝试了一些 C++ 代码作为链接,但不知道如何编写。

  • 中,或多或少可以实现这一点 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 变量不包括在内。

    受到 这个答案的 Bergi .

  • 引用 14

    是也不是。几乎在所有情况下都是“不是”。如果你想检查全局范围,那么“是”但只能以有限的方式进行。请看以下示例:

    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
    

    因此,可以在当前范围内列出一些变量,但 它不可靠、不简洁、不高效或不易访问。

    更好的问题是, 为什么你想知道哪些变量在范围内?

  • mr.T 1月前 0 只看Ta
    引用 15

    如果您使用节点,只需将单词 \'window\' 更改为 \'global\'...或者您可以使用单词 \'this\',但这在 \'use strict\' 下是被禁止的

  • 我添加了一行代码来检查 hasOwnProperty。例如: for ( var i in window ) { if (window.hasOwnProperty(i)) { console.log(i, window[i]); }}。这至少会减少继承的属性,并且您的变量将只存在于大约 50 个其他属性中。

  • 谢谢,如果您需要检查某个变量是否存在以及它在非常复杂或由其他人设计的环境中是如何定义的,这可能会很有用。

  • 你有多少时间?

    如果你 ḧ̸̬̦́̒͑̌͝ͅa̵͍͖͛t̴̪̟̬̖̾́̋͗̏ͅe̸̳̊̍̈́͌͝ 你的 CPU,你可以强行测试每个有效的变量名,并 eval 逐一查看它是否产生一个值!

    以下代码片段尝试前 1000 个暴力破解字符串,这足以在范围内找到人为设计的变量名称:

    let alpha = 'abcdefghijklmnopqrstuvwxyz';
    let everyPossibleString = function*() {
      yield '';
      for (let prefix of everyPossibleString()) for (let char of alpha) yield `${prefix}${char}`;
    };
    let allVarsInScope = (iterations=1000) => {  
      let results = {};
      let count = 0;
      for (let bruteforceString of everyPossibleString()) {
        if (!bruteforceString) continue; // Skip the first empty string
        try { results[bruteforceString] = eval(bruteforceString); } catch(err) {}
        if (count++ > iterations) break;
      }
      return results;
    };
    
    let myScope = (() => {
        
      let dd = 'ddd';
      let ee = 'eee';
      let ff = 'fff';
      
      ((gg, hh) => {
        
        // We can't call a separate function, since that function would be outside our
        // scope and wouldn't be able to see any variables - but we can define the
        // function in place (using `eval(allVarsInScope.toString())`), and then call
        // that defined-in-place function
        console.log(eval(allVarsInScope.toString())());
        
      })('ggg', 'hhh');
      
    })();

    此脚本最终(经过长时间)将找到所有范围变量名,以及 abc nifty swell ,我创建的一些示例变量。请注意,它只会找到由字母字符组成的变量名。

    let preElem = document.getElementsByClassName('display')[0];
    let statusElem = document.getElementsByClassName('status')[0];
    let alpha = 'abcdefghijklmnopqrstuvwxyz';
    alpha += alpha.toUpperCase();
    let everyPossibleString = function*() {
      yield '';
      for (let prefix of everyPossibleString()) for (let char of alpha) yield `${prefix}${char}`;
    };
    
    (async () => {
      
      let abc = 'This is the ABC variable :-|';
      let neato = 'This is the NEATO variable :-)';
      let swell = 'This is the SWELL variable :-D';
      
      let ignoreRegex = /^(?:t(?:his|op)|self|window)$/;
      let results = {};
      let batch = 100;
      let waitMs = 25;
      let count = 0;
      let startStr = null;
      let t = null;
      
      for (let bruteStr of everyPossibleString()) {
        
        // Some property accesses cause problems within 's iframe snippet
        // system - we'll bypass these problematic properties
        if (ignoreRegex.test(bruteStr)) continue;
        
        if (count === 0) {
          t = Date.now();
          startStr = bruteStr;
        }
        
        try { results[bruteStr] = eval(bruteStr); } catch(err) {}
        
        if (count++ >= batch) {
          
          count = 0;
          
          // Update the html
          statusElem.innerHTML = `Did batch of ${batch} from ${startStr} -> ${bruteStr} in ${waitMs.toFixed(0)}ms`;
          preElem.innerHTML = JSON.stringify(results, null, 2);
          
          // Optimize `batch` based on how well the CPU is holding up
          let dur = (Date.now() - t) + 2; // +2ms for breathing room
          let estimatedMaxBatch = batch * (waitMs / dur);
          batch = Math.round(batch * 0.8 + estimatedMaxBatch * 0.2);
          
          // 
          await new Promise(r => setTimeout(r, waitMs));
          
        }
                
      }
      
      console.log('Done...'); // Will literally never happen
      
    })();
    html, body { position: fixed; left: 0; top: 0; right: 0; bottom: 0; margin: 0; padding: 0; overflow: hidden }
    .display {
      position: fixed;
      box-sizing: border-box;
      left: 0; top: 0;
      bottom: 30px; right: 0;
      overflow-y: scroll;
      white-space: pre;
      font-family: monospace;
      padding: 10px;
      box-shadow: inset 0 0 10px 1px rgba(0, 0, 0, 0.3);
    }
    .status {
      position: fixed;
      box-sizing: border-box;
      left: 0; bottom: 0px; right: 0; height: 30px; line-height: 30px;
      padding: 0 10px;
      background-color: rgba(0, 0, 0, 1);
      color: rgba(255, 255, 255, 1);
      font-family: monospace;
    }
    <div class="display"></div>
    <div class="status"></div>

    我非常清楚,几乎没有任何情况是可行的

  • 我希望我能多次点赞,只为纯粹而可怕的美丽:console.log(eval(allVarsInScope.toString())());

  • 你不能。

    变量、函数声明的标识符和函数代码的参数被绑定为 变量对象 ,该属性是不可访问的。

    参见:

    • 作用域链和标识符解析
返回
作者最近主题: