Функция Immediate Parent отсутствует в цепочке видимости возвращенной функции [duplicate]

Используйте функцию callback() внутри успеха foo(). Попробуйте таким образом. Это просто и легко понять. & nbsp;

var lat = "";
var lon = "";
function callback(data) {
    lat = data.lat;
    lon = data.lon;
}
function getLoc() {
    var url = "http://ip-api.com/json"
    $.getJSON(url, function(data) {
        callback(data);
    });
}

getLoc();
114
задан Gabe Kopley 9 February 2015 в 23:19
поделиться

5 ответов

Я нашел отчет о выпуске v8 , который именно о том, что вы просите.

Теперь, чтобы суммировать то, что сказано в этом выпуске ... v8 может хранить переменные, которые являются локальными для функции в стеке или в объекте «context», который живет в куче. Он будет выделять локальные переменные в стеке, пока функция не содержит никакой внутренней функции, которая относится к ним. Это оптимизация. Если любая внутренняя функция ссылается на локальную переменную, эта переменная будет помещена в объект контекста (т. Е. В куче, а не в стеке). Случай eval является особенным: если он вообще вызван внутренней функцией, все локальные переменные помещаются в объект контекста.

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

Отладчик не может проверить те переменные, которые находятся в стеке. Что касается проблемы, возникающей при отладке, один из участников проекта говорит, что :

Единственное решение, о котором я мог думать, это то, что всякий раз, когда devtools включен, мы уничтожаем весь код и перекомпилируем с принудительным контекстным распределением. Это резко изменило бы производительность при использовании devtools.

Вот пример «если какая-либо внутренняя функция относится к переменной, поместите ее в объект контекста». Если вы запустите это, вы сможете получить доступ к x в инструкции debugger, хотя x используется только в функции foo, , которая никогда не называется !

function baz() {
  var x = "x value";
  var z = "z value";

  function foo () {
    console.log(x);
  }

  function bar() {
    debugger;
  };

  bar();
}
baz();
111
ответ дан Louis 27 August 2018 в 09:41
поделиться

Я также заметил это в nodejs. Я полагаю (и я допускаю, что это только предположение), что при компиляции кода, если x не появляется внутри bar, он не делает x доступным в области bar. Это, вероятно, делает его несколько более эффективным; проблема в том, что кто-то забыл (или не заботился) о том, что даже если в bar нет x, вы можете решить запустить отладчик и, следовательно, еще нужно получить доступ к x изнутри bar.

6
ответ дан David Knipe 27 August 2018 в 09:41
поделиться

Ничего себе, действительно интересно!

Как уже упоминалось, это, по-видимому, связано с scope, но более конкретно, связано с debugger scope. Когда внедренный скрипт оценивается в инструментах разработчика, он, как представляется, определяет ScopeChain, что приводит к некоторой причудливости (поскольку оно связано с областью инспектора / отладчика). Вариант того, что вы разместили, это:

(EDIT - на самом деле, вы упомянули об этом в своем исходном вопросе, yikes, мой плохой! )

function foo() {
  var x = "bat";
  var y = "man";

  function bar() {
    console.log(x); // logs "bat"

    debugger; // Attempting to access "y" throws the following
              // Uncaught ReferenceError: y is not defined
              // However, x is available in the scopeChain. Weird!
  }
  bar();
}
foo();

Для амбициозного и / или любопытного масштаба (heh) из источника, чтобы узнать, что происходит:

https://github.com/WebKit/webkit/tree/master/Source / JavaScriptCore / inspector https://github.com/WebKit/webkit/tree/master/Source/JavaScriptCore/debugger

2
ответ дан Jack 27 August 2018 в 09:41
поделиться

Я подозреваю, что это связано с перестановкой переменных и функций. JavaScript приносит все объявления переменных и функций в начало функции, в которой они определены. Дополнительная информация здесь: http://jamesallardice.com/explaining-function-and-variable-hoisting-in-javascript/

Бьюсь об заклад, что Chrome вызывает точку прерывания с переменной, недоступной для области видимости, потому что в функции больше ничего нет. Это работает:

function baz() {
  var x = "foo";

  function bar() {
    console.log(x); 
    debugger;
  };
  bar();
}

Как это делает:

function baz() {
  var x = "foo";

  function bar() {
    debugger;
    console.log(x);     
  };
  bar();
}

Надеюсь, что и / или ссылка выше помогает. Это мой любимый вид вопросов SO, BTW:)

0
ответ дан markle976 27 August 2018 в 09:41
поделиться

Как @Louis сказал, что это вызвано оптимизациями v8. Вы можете перемещать стек вызовов в кадр, где эта переменная видна:

Или заменить debugger на

eval('debugger');

eval отключит текущий кусок

14
ответ дан OwnageIsMagic 27 August 2018 в 09:41
поделиться
Другие вопросы по тегам:

Похожие вопросы: