Получить все значения замыкания в node.js или V8

Например, если мы допустим следующий код:

var f = function() { return 'hello world' };
var x = 10;
var y = 314;

var g = function() {
    var buf = [], xx = x;
    while (xx--)
        buf.append(f() + ' ');
    return buf.join('');
}

Я могу получить фактический "код" как строку g с g.toString(). Однако это не означает (очевидно), что f и x - члены замыкания g (извините, если я не совсем правильно использую эти условия.)

Есть ли способ запросить функцию для ее закрытия? В идеале я мог бы получить объект вроде:

{ 'f' : f, 'x': x } // note that `y` is not here

Если мне нужно перейти на С++ для специальных взаимодействий с V8, это хорошо, хотя как-то сделать это в чистом JavaScript было бы лучше.


Я знаю, что это немного странный вопрос, но у меня есть законная причина для этого!

Ответ 1

Я нашел эту дискуссию в реализациях закрытия V8. Похоже, что объект С++, который вы ищете, это Context.

Ответ 2

Edit:

Такой метод не существует. Если вы делаете это в JavaScript, то лучше всего написать парсер, который определит, какие переменные закрывается функцией.

Если вы напишете такой метод, поделитесь:)

Оригинальное сообщение:

В вашем примере закрытие g имеет доступ к f и y. x объявляется как локальная переменная, поэтому x НЕ равно 10. Не существует специального метода, который расскажет вам, какие переменные закрывается функцией.

Если g был методом объекта, вы можете использовать функцию объекта hasOwnProperty для определения того, какие свойства доступны для объекта. AFAIK, что единственное, что подходит для определения того, к каким переменным имеет доступ функция в JavaScript.

Ответ 3

Вы хотите иметь список всех переменных, которые будут использоваться внутри этой функции, правильно? Быстрым и грязным способом, вероятно, было бы использовать что-то вроде анализатора и материала AST из UglifyJS, чтобы выполнить функцию, чтобы затем получить список всех переменных и т.д.

Ответ 4

В коде, который вы опубликовали, нет закрытий. Вы можете получить значение любой переменной, которую хотите в любой момент, и это будет то, что видит ваша функция g. Просто потому, что вы вызываете функцию из другой функции, это не делает закрытие. Для того чтобы быть замыканием f, должно было бы быть переменная области g-функции, и это не так. Обе эти функции находятся в том же объеме, что и ваши x и y, предположительно глобальные. Если бы вы сказали, что оберните весь щенок в одну большую функцию, все они будут находиться в одном и том же объеме, но если вы хотите вернуть f и g из всеобъемлющей функции, тогда вы будете смотреть на закрытие, где x и y будут быть закрытым для функции возврата, разделяемой с f и g. Тогда вам понадобится какая-то форма функции getter, которая также должна быть возвращена и может связываться, установив значение переменной наблюдения на одну ссылку в цепочке областей видимости.

Как и сейчас, с представленным кодом x является x и y, поэтому, проверяйте их в любое время, и это их значение, что также отображает как f, так и g.

Рики Ги

Ответ 5

Как сказал Рики Ги, здесь нет проблем, потому что переменные глобальны, поэтому вы можете добраться до них через глобальный объект. Однако, если предположить, что код не был глобальным, то нет, вы не можете извлечь ссылку на переменные f, x и y (или их значения) из замыкания g.

Вы не можете сделать это в JavaScript, и вы не можете это сделать через API V8. Очевидно, что данные находятся где-то, но V8 даже не пытается сделать свои внутренние структуры данных доступными.