Получение всех переменных в области видимости - PullRequest
172 голосов
/ 12 января 2010

Есть ли способ получить все переменные, которые в настоящее время находятся в области видимости в JavaScript?

Ответы [ 9 ]

82 голосов
/ 24 августа 2014

Хотя все отвечают « Нет », и я знаю, что «Нет» - правильный ответ, но если вам действительно нужно получить локальные переменные функции, существует ограниченный путь.

Рассмотрим эту функцию:

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 . Но все же вы можете использовать цепочки caller (arguments.callee.caller.caller.caller) в цикле, чтобы найти локальные переменные функций вызывающей стороны. Если у вас есть все имена локальных переменных, значит, у вас есть переменные области действия . С именами переменных у вас есть доступ к значениям с простым eval.

80 голосов
/ 12 января 2010

Нет.Переменные «в области видимости» определяются «цепочкой областей действия», которая недоступна программно.

Подробнее (довольно много) можно найти в спецификации 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 для разработки), или Dragonfly в Opera, или «Инструменты разработчика F12» в IE.И прочитайте все файлы JavaScript, которые они вам предоставляют.И бить их по голове для правильных документов.: -)

31 голосов
/ 13 января 2010

Да и нет. «Нет» почти в каждой ситуации. «Да», но только ограниченным образом, если вы хотите проверить глобальную область. Возьмите следующий пример:

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

Таким образом, можно перечислить некоторые переменные в текущей области, но это не надежно, кратко, эффективно или легко доступно.

Лучший вопрос: почему вы хотите знать, какие переменные находятся в области видимости?

17 голосов
/ 17 января 2017

В 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 переменные не включены.

Вдохновлен этим ответом Берги .

16 голосов
/ 12 января 2010

Вы не можете.

Переменные, идентификаторы объявлений функций и аргументы для кода функции, связаны как свойства объекта переменной , который недоступен.

Смотри также:

7 голосов
/ 28 декабря 2012

Самый простой способ получить доступ к переменным в определенной области

  1. Открыть Инструменты разработчика> Ресурсы (в Chrome)
  2. Открыть файл с помощью функции, которая имеет доступ к этой области (подсказка cmd / ctrl + p, чтобы найти файл)
  3. Установите точку останова внутри этой функции и запустите ваш код
  4. Когда он останавливается на вашей точке останова, вы можете получить доступ к области видимости через консоль (или окно области видимости)

Примечание: Вы хотите сделать это против неунифицированного JS.

Самый простой способ показать все не частные переменные

  1. Открытая консоль (в Chrome)
  2. Тип: this.window
  3. Нажмите Enter

Теперь вы увидите дерево объектов, которое можно развернуть со всеми объявленными объектами.

7 голосов
/ 23 мая 2012

Как все заметили: ты не можешь. Но вы можете создать объект и назначить каждый объявленный вами объект этому объекту. Таким образом, вы можете легко проверить свои переменные:

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
3 голосов
/ 19 ноября 2015

Если вы просто хотите проверить переменные вручную, чтобы помочь отладке, просто запустите отладчик:

debugger;

Прямо в консоль браузера.

0 голосов
/ 25 января 2017
  1. получить список всех и каждого слова, которое когда-либо было написано или набрано каким-либо образом или каким-либо образом любым человеком с начала времен (безусловно, конечный список в математическом смысле.)

  2. поместите их все в один большой массив, снова напечатав их все в консоли разработчика (в виде строк, чтобы вы не получили здесь ошибку).

  3. создайте новый массив и сделайте цикл над вашим конечным списком, запихивая в новый массив, если try / catch (просто делая это в try) не заканчивается в catch из-за ReferenceError (используя eval для «unstring»)потому что вам нужна ошибка здесь, если не в области видимости).

  4. Я принимаю это обратно.Список, о котором я говорил в пункте 1, недостаточно велик.Они могли создавать переменные через window [randomlyGeneratedString] = что-то.Лучшее зацикливание на всех строках, которые могут быть созданы любой компьютерной программой, останавливающейся в разумные допустимые сроки - скажем, время с момента изобретения компютера.


Хорошо, серьезно,Вы можете сделать это так, используя в качестве списка в 1) то, что вы получите, запустив esprima.parse на всей кодовой базе и пройдя по дереву для вещей, называемых «Идентификатор», и сохраняя их «имя».Но тогда вы пропустите создаваемые переменные, как в окне ["file_" + i] = бла, см. 4.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...