significa que paused extension depurar debugger debuggear debug chrome javascript google-chrome google-chrome-devtools

que - javascript console chrome



¿Por qué el depurador de Chrome cree que la variable local cerrada no está definida? (5)

Con este código:

function baz() { var x = "foo"; function bar() { debugger; }; bar(); } baz();

Me sale este resultado inesperado:

Cuando cambio el código:

function baz() { var x = "foo"; function bar() { x; debugger; }; bar(); }

Obtengo el resultado esperado:

Además, si hay alguna llamada a eval dentro de la función interna, puedo acceder a mi variable como quiero hacerlo (no importa lo que pase a eval ).

Mientras tanto, las herramientas de desarrollo de Firefox ofrecen el comportamiento esperado en ambas circunstancias.

¿Qué pasa con Chrome que el depurador se comporta de manera menos conveniente que Firefox? He observado este comportamiento durante algún tiempo, hasta la versión 41.0.2272.43 beta incluida (64 bits).

¿Es que el motor de JavaScript de Chrome "aplana" las funciones cuando puede?

Curiosamente, si agrego una segunda variable a la que se hace referencia en la función interna, la variable x aún no está definida.

Entiendo que a menudo hay peculiaridades con el alcance y la definición de variables cuando se usa un depurador interactivo, pero me parece que, según la especificación del lenguaje, debería haber una "mejor" solución para estas peculiaridades. Así que tengo mucha curiosidad si esto se debe a la optimización de Chrome más allá de Firefox. Y también si estas optimizaciones pueden deshabilitarse fácilmente durante el desarrollo (¿quizás deberían deshabilitarse cuando las herramientas de desarrollo están abiertas?).

Además, puedo reproducir esto con puntos de interrupción, así como la declaración del debugger .


Como @Louis dijo que fue causado por las optimizaciones de v8. Puede recorrer la pila de llamadas para enmarcar donde esta variable es visible:

O reemplace el debugger con

eval(''debugger'');

eval desoptizará parte actual


He encontrado un informe de problema de v8 que trata precisamente de lo que estás preguntando.

Ahora, para resumir lo que se dice en ese informe de problema ... v8 puede almacenar las variables que son locales para una función en la pila o en un objeto de "contexto" que vive en el montón. Asignará variables locales en la pila siempre que la función no contenga ninguna función interna que se refiera a ellas. Es una optimización . Si alguna función interna se refiere a una variable local, esta variable se colocará en un objeto de contexto (es decir, en el montón en lugar de en la pila). El caso de eval es especial: si una función interna lo llama en absoluto, todas las variables locales se colocan en el objeto de contexto.

La razón del objeto de contexto es que, en general, podría devolver una función interna de la externa y luego la pila que existía mientras se ejecutaba la función externa ya no estará disponible. Entonces, cualquier cosa a la que acceda la función interna debe sobrevivir a la función externa y vivir en el montón en lugar de en la pila.

El depurador no puede inspeccionar esas variables que están en la pila. Con respecto al problema encontrado en la depuración, un miembro del proyecto says :

La única solución que se me ocurre es que siempre que esté activado devtools, desoptiríamos todo el código y volveríamos a compilar con la asignación de contexto forzada. Sin embargo, eso reduciría drásticamente el rendimiento con devtools habilitado.

Aquí hay un ejemplo de "si alguna función interna se refiere a la variable, póngala en un objeto de contexto". Si ejecuta esto, podrá acceder a x en la declaración del debugger aunque x solo se use en la función foo , ¡ que nunca se llama !

function baz() { var x = "x value"; var z = "z value"; function foo () { console.log(x); } function bar() { debugger; }; bar(); } baz();


Sospecho que esto tiene que ver con la elevación de variables y funciones. JavaScript lleva todas las declaraciones de variables y funciones a la parte superior de la función en la que se definen. Más información aquí: http://jamesallardice.com/explaining-function-and-variable-hoisting-in-javascript/

Apuesto a que Chrome está llamando al punto de ruptura con la variable no disponible para el alcance porque no hay nada más en la función. Esto parece funcionar:

function baz() { var x = "foo"; function bar() { console.log(x); debugger; }; bar(); }

Como hace esto:

function baz() { var x = "foo"; function bar() { debugger; console.log(x); }; bar(); }

Espero esto, y / o el enlace de arriba ayuda. Este es mi tipo favorito de preguntas SO, por cierto :)


También he notado esto en nodejs. Creo (y admito que esto es solo una suposición) que cuando se compila el código, si x no aparece dentro de la bar , no hace que x esté disponible dentro del alcance de la bar . Esto probablemente lo hace un poco más eficiente; el problema es que alguien olvidó (o no le importó) que incluso si no hay una x en la bar , puede decidir ejecutar el depurador y, por lo tanto, aún necesita acceder a x desde la bar interior.


Wow, muy interesante!

Como otros han mencionado, esto parece estar relacionado con el scope , pero más específicamente, relacionado con el debugger scope . Cuando la secuencia de comandos inyectada se evalúa en las herramientas del desarrollador, parece determinar un ScopeChain , lo que resulta en una peculiaridad (ya que está vinculado al alcance del inspector / depurador). Una variación de lo que publicaste es esta:

(EDITAR: en realidad, mencionas esto en tu pregunta original, ¡ ay, qué mal! )

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

Para los ambiciosos y / o curiosos, busque (heh) la fuente para ver qué está pasando:

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