Esto es de alcance estático. Las declaraciones dentro de una función tienen un alcance dentro de esa función.
Javascript tiene un comportamiento peculiar, sin embargo, que es que sin el var de palabras clave, que ha implicado una variable global . Eso es lo que estás viendo en tu prueba. Su variable "d" está disponible porque es un global implícito, a pesar de estar escrito dentro del cuerpo de una función.
Además, para responder a la segunda parte de su pregunta: Existe una función en cualquier ámbito que se declare, al igual que una variable.
Sidenote: Probablemente no desee variables globales, especialmente las implícitas. Se recomienda utilizar siempre la palabra clave var para evitar confusiones y mantener todo limpio.
Nota al margen: El estándar ECMA no es probablemente el lugar más útil para encontrar respuestas sobre Javascript, aunque ciertamente no es una mala recursos. Recuerde que javascript en su navegador es solo una implementación de ese estándar, por lo que el documento de estándares le dará las reglas que (en su mayoría) siguieron los implementadores cuando se creó el motor javascript. No puede ofrecer información específica sobre las implementaciones que le interesan, a saber, los principales navegadores. Hay un par de libros en particular que le brindarán información muy directa sobre cómo se comportan las implementaciones de javascript en los principales navegadores. Para ilustrar la diferencia, incluiré extractos a continuación de la especificación ECMAScript y un libro sobre Javascript. Creo que estarás de acuerdo en que el libro da una respuesta más directa.
Aquí es desde el ECMAScript Language Specification:
10,2 Entrando en un contexto de ejecución
Cada función y constructor de llamada entra en un nuevo contexto de ejecución, incluso si una función está llamando a sí mismo recursivamente. Cada devolución sale de un contexto de ejecución . Una excepción lanzada, si no se detecta, también puede salir de uno o más contextos de ejecución.
Cuando el control entra en un contexto de ejecución, la cadena de ámbito se crea y inicializado, instanciación variables se lleva a cabo, y se determina el este valor.
El inicialización de la cadena de ámbito, instanciación variable y la determinación del este valor depende del tipo de código que está siendo introducido.
Aquí es de Javascript: The Definitive Guide (5th Edition) de O'Reilly:
8.8.1 ámbito léxico
Funciones en JavaScript léxica son en lugar de ámbito dinámico. Esto significa que se ejecutan en el alcance en que están definidos, no en el ámbito desde el que se ejecutan. Cuando se define una función , se guarda la cadena actual de alcance y se convierte en parte del estado interno de la función . ...
Muy recomendable para cubrir este tipo de preguntas es el libro de Douglas Crockford:
JavaScript, The Good Parts http://oreilly.com/catalog/covers/9780596517748_cat.gif
Javascript, The Good Parts, también de O'Reilly.
Exactamente a la derecha - en términos generales, 'function a() {}' es equivalente a 'var a = function() {}' (hay algunas diferencias semánticas menores, pero nada demasiado significativo). – olliej
gracias, pero ¿dónde encuentro las siguientes afirmaciones en el estándar ECMAScript (¿o falta?): "Las declaraciones dentro de una función tienen un alcance dentro de esa función". En mi impresión, la semántica de "var a = function() {}" está bien definida, pero no la de la declaración "function a() {...}". –
El estándar ECMAScript solo le dará las pautas para implementar ECMAScript, de las cuales Javascript es solo un miembro de la familia. Entonces no encontrará esa declaración exacta, pero hay otros recursos que pueden ayudarlo. Ver mi nota adicional arriba. – keparo