¿Cuál es el alcance de las variables en javascript?

¿Cuál es el alcance de las variables en javascript? ¿Tienen la misma área dentro y no fuera de la función? ¿O incluso importa? Además, ¿dónde se almacenan las variables si se definen globalmente?

1742
01 февр. lYriCAlsSH set 01 feb. 2009-02-01 11:27 '09 a las 11:27 2009-02-01 11:27
@ 25 respuestas

Pienso en lo que puedo hacer para darte un montón de ejemplos para estudiar. Los programadores de Javascript son juzgados prácticamente por lo bien que entienden el alcance. Puede ser completamente intuitivo de vez en cuando.

  1. Variable con alcance global.

     // global scope var a = 1; function one() { alert(a); // alerts '1' } 
  2. Area local

     // global scope var a = 1; function two(a) { // passing (a) makes it local scope alert(a); // alerts the given argument, not the global value of '1' } // local scope again function three() { var a = 3; alert(a); // alerts '3' } 
  3. Intermedio : en JavaScript no existe un área de bloque (ES5; ES6 introduce let )

    un

     var a = 1; function four() { if (true) { var a = 4; } alert(a); // alerts '4', not the global value of '1' } 

    b.

     var a = 1; function one() { if (true) { let a = 4; } alert(a); // alerts '1' because the 'let' keyword uses block scoping } 
  4. Intermedio : propiedades del objeto

     var a = 1; function Five() { this.a = 5; } alert(new Five().a); // alerts '5' 
  5. Opcional : Clausura.

     var a = 1; var six = (function() { var a = 6; return function() { // JavaScript "closure" means I have access to 'a' in here, // because it is defined in the function in which I was defined. alert(a); // alerts '6' }; })(); 
  6. Opcional : Resolución basada en prototipo

     var a = 1; function seven() { this.a = 7; } // [object].prototype.property loses to // [object].property in the lookup chain. For example... // Won't get reached, because 'a' is set in the constructor above. seven.prototype.a = -1; // Will get reached, even though 'b' is NOT set in the constructor. seven.prototype.b = 8; alert(new seven().a); // alerts '7' alert(new seven().b); // alerts '8' 

  7. Global + Local : estuche extra duro

     var x = 5; (function () { console.log(x); var x = 10; console.log(x); })(); 

    Esto imprimirá undefined y 10 lugar de 5 y 10 porque JavaScript siempre mueve las declaraciones de variables (no las inicializaciones) a la parte superior de la región, lo que hace que el código sea equivalente:

     var x = 5; (function () { var x; console.log(x); x = 10; console.log(x); })(); 
  8. Variable de captura

     var e = 5; console.log(e); try { throw 6; } catch (e) { console.log(e); } console.log(e); 

    Esto imprimirá 5 , 6 , 5 . Dentro del objeto catch e hay sombras de variables globales y locales. Pero esta escala especial está destinada solo para la variable capturada. Si escribes var f; dentro de una cláusula catch, es exactamente lo mismo que si lo hubieras definido antes o después del bloque try-catch.

2292
01 февр. La respuesta está dada por Tríptico 01 de febrero. 2009-02-01 11:58 '09 a las 11:58 2009-02-01 11:58

Javascript usa cadenas de alcance para determinar el alcance de una función dada. Por lo general, hay un alcance global, y cada función definida tiene su propio alcance anidado. Cualquier función definida dentro de otra función tiene un área local asociada con una función externa. Esta es siempre la posición en la fuente que define el alcance.

El elemento en la cadena de alcance es básicamente un Mapa con un puntero a su área principal.

Cuando la variable está habilitada, javascript se ejecuta en el área interna y busca fuera.

221
01 февр. La respuesta se da krosenvold 01 feb. 2009-02-01 11:35 '09 a las 11:35 2009-02-01 11:35

Las variables declaradas globalmente tienen un alcance global. Las variables declaradas dentro de las funciones están vinculadas a esta función y sombrean las variables globales con el mismo nombre.

(Estoy seguro de que hay muchas sutilezas que los programadores reales de JavaScript pueden describir en otras respuestas. En particular, conocí esta página sobre lo que esto significa en cualquier momento. Espero que este enlace de introducción sea suficiente para que pueda comenzar a trabajar. .)

95
01 февр. Jon Skeet responde 01 feb. 2009-02-01 11:31 '09 a las 11:31 am 2009-02-01 11:31

Javascript de la vieja escuela

Tradicionalmente, JavaScript realmente tiene solo dos tipos de alcance:

  • Área global Las variables son conocidas en toda la aplicación desde que se lanzó la aplicación (*)
  • Área funcional : las variables se conocen en la función en la que se declaran, desde el principio de la función (*)

No me detendré en esto en detalle, ya que ya hay muchas otras respuestas que explican la diferencia.


JavaScript moderno

Las últimas especificaciones de JavaScript ahora también permiten el uso de una tercera área:

  1. Escala de bloques : las variables se conocen en el bloque en el que se declaran, desde el momento en que se declaran hacia adelante (**)

¿Cómo crear bloques de áreas variables?

Tradicionalmente, creas tus variables de la siguiente manera:

 var myVariable = "Some text"; 

Las variables de visibilidad bloqueadas se crean de la siguiente manera:

 let myVariable = "Some text"; 

¿Cuál es la diferencia entre un área funcional y un tamaño de bloque?

Para comprender la diferencia entre un área funcional y un área de bloque, considere el siguiente código:

 // i IS NOT known here // j IS NOT known here // k IS known here, but undefined // l IS NOT known here function loop(arr) { // i IS known here, but undefined // j IS NOT known here // k IS known here, but has a value only the second time loop is called // l IS NOT known here for( var i = 0; i < arr.length; i++ ) { // i IS known here, and has a value // j IS NOT known here // k IS known here, but has a value only the second time loop is called // l IS NOT known here }; // i IS known here, and has a value // j IS NOT known here // k IS known here, but has a value only the second time loop is called // l IS NOT known here for( let j = 0; j < arr.length; j++ ) { // i IS known here, and has a value // j IS known here, and has a value // k IS known here, but has a value only the second time loop is called // l IS NOT known here }; // i IS known here, and has a value // j IS NOT known here // k IS known here, but has a value only the second time loop is called // l IS NOT known here } loop([1,2,3,4]); for( var k = 0; k < arr.length; k++ ) { // i IS NOT known here // j IS NOT known here // k IS known here, and has a value // l IS NOT known here }; for( let l = 0; l < arr.length; l++ ) { // i IS NOT known here // j IS NOT known here // k IS known here, and has a value // l IS known here, and has a value }; loop([1,2,3,4]); // i IS NOT known here // j IS NOT known here // k IS known here, and has a value // l IS NOT known here 

Aquí vemos que nuestra variable j conocida solo en el primer bucle for, pero no antes y no más tarde. Sin embargo, nuestra variable i conocida en toda la función.

Además, tenga en cuenta que las variables de alcance son desconocidas antes de que se declaren, porque no se plantean. Tampoco está permitido anular la misma variable con una región en el mismo bloque. Esto lleva al hecho de que las variables con áreas altamente especializadas son menos propensas a errores que las variables copiadas global o funcionalmente que aumentan y que no conducen a errores en el caso de declaraciones múltiples.


¿Es seguro usar bloques de áreas variables hoy?

Independientemente de si es seguro usarlo hoy, depende de su entorno:

  • Si está escribiendo el código de JavaScript del servidor ( Node.js ), puede usar la instrucción let forma segura.

  • Si está escribiendo un código del lado del cliente y está usando un transpiler (por ejemplo, Traceur ), puede usar la declaración de permiso de forma segura, pero su código probablemente será óptimo en términos de rendimiento.

  • Si está escribiendo el código del lado del cliente y no está utilizando Transpiler, debe considerar la compatibilidad con el navegador.

    Hoy, 23 de febrero de 2016, estos son algunos navegadores que no admiten o solo tienen soporte parcial:

    • Internet Explorer 10 y anteriores (sin soporte)
    • Firefox 43 y anteriores (sin soporte)
    • Safari 9 e inferior (sin soporte)
    • Opera Mini 8 e inferior (sin soporte)
    • Navegador Android 4 y anteriores (sin soporte)
    • Opera 36 e inferior (soporte parcial)
    • Chome 51 e inferior (soporte parcial)

2019

23 февр. Respuesta dada por John Slegers 23 de febrero 2016-02-23 21:51 '16 a las 21:51 2016-02-23 21:51

Aquí hay un ejemplo:

 <script> var globalVariable = 7; //==window.globalVariable function aGlobal( param ) { //==window.aGlobal(); //param is only accessible in this function var scopedToFunction = { //can't be accessed outside of this function nested : 3 //accessible by: scopedToFunction.nested }; anotherGlobal = { //global because there no `var` }; } </script> 

Necesitas investigar el cierre y usarlos para crear miembros privados .

35
01 февр. la respuesta se da geowa4 01 feb. 2009-02-01 11:48 '09 a las 11:48 2009-02-01 11:48

La clave, como yo lo entiendo, es que Javascript tiene un alcance y un área más general del dominio C.

Aquí hay un buen artículo sobre este tema.

28
15 мая '12 в 20:38 2012-05-15 20:38 La respuesta fue dada por James McMahon el 15 de mayo de 2012 a las 20:38 2012-05-15 20:38

En "Javascript 1.7" (extensión de Mozilla para Javascript), también puede declarar las variables de la región de volumen utilizando la instrucción let :

  var a = 4; let (a = 3) { alert(a); // 3 } alert(a); // 4 
23
06 апр. La respuesta se da kennytm 06 de abril. 2010-04-06 14:19 '10 a las 2:19 pm 2010-04-06 14:19

La idea de definir el reino de JavaScript cuando fue desarrollado originalmente por Brendan Eich se tomó del lenguaje HyperTalk de los scripts de HyperCard .

En este idioma, las pantallas se hicieron similares a una pila de fichas. Había una tarjeta principal, llamada el fondo. Era transparente y puede verse como una carta inferior. Cualquier contenido en este mapa base fue compartido con los mapas ubicados encima de él. Cada tarjeta colocada en la parte superior tenía su propio contenido, que tenía prioridad sobre la tarjeta anterior, pero si se deseaba, tenía acceso a las tarjetas anteriores.

Así es como se desarrolla el sistema de revisión de JavaScript. Él sólo tiene nombres diferentes. Los mapas en JavaScript son conocidos como contextos de ejecución ECMA . Cada uno de estos contextos contiene tres partes principales. Entorno variable, entorno léxico y esta vinculación. Volviendo a la referencia del mapa, el entorno léxico contiene todo el contenido de los mapas anteriores a continuación en la pila. El contexto actual se encuentra en la parte superior de la pila, y cualquier contenido declarado allí se almacenará en un entorno variable. El entorno variable tendrá prioridad en el caso de denominación de colisión.

Este enlace apuntará al objeto contenedor. A veces, los contextos o los contextos de ejecución cambian sin cambiar el objeto del objeto, por ejemplo, en una función declarada, donde el objeto que contiene puede ser una window o un constructor.

Estos contextos de ejecución se crean bajo cualquier control de tiempo. El control se transmite cuando el código comienza a ejecutarse, y esto se realiza principalmente a partir de la ejecución de la función.

Así que esta es una explicación técnica. En la práctica, es importante recordar que en JavaScript

  • Los campos son técnicamente "Contextos de ejecución".
  • Los contextos forman una pila de entornos en los que se almacenan las variables.
  • La parte superior de la pila tiene prioridad (la parte inferior es el contexto global)
  • Cada función crea un contexto de ejecución (pero no siempre un nuevo enlace)

Al aplicar esto a uno de los ejemplos anteriores (5. "Cierre") en esta página, puede seguir la pila de contextos de ejecución. En este ejemplo, hay tres contextos en la pila. Están definidos por el contexto externo, el contexto en la función llamada inmediatamente, llamado por la var seis, y el contexto en la función return dentro de la función var seis, llamado inmediatamente.

i) Contexto externo. Tiene un entorno variable a = 1
ii) En el contexto de IIFE, tiene el entorno léxico a = 1, pero la variable de entorno a = 6, que tiene prioridad en la pila iii) El contexto devuelto de la función, tiene el entorno léxico a = 6, y este valor es referenciado por la advertencia en la llamada.

2019

14 сент. La respuesta la da Travis J el 14 de septiembre. 2015-09-14 23:29 '15 a las 11:29 pm 2015-09-14 23:29

1) Hay un alcance global, alcance y alcance de la búsqueda y captura. No hay nivel de "bloque" en la variable de nivel. Los operadores con y captura captan los nombres en sus bloques.

2) Las áreas se adjuntan a funciones hasta el área global.

3) Las propiedades se resuelven pasando una cadena prototipo. La instrucción with asigna los nombres de las propiedades de un objeto al área léxica especificada por el bloque c.

EDITAR: Se propone ECMAAScript 6 (Harmony) para admitir let, y sé que Chrome permite la marca de "armonía", por lo que tal vez sea compatible.

Permita que haya soporte para determinar el nivel de un bloque, pero necesita usar una palabra clave para que suceda.

EDITAR: Basado en el hecho de que Benjamin señaló los comentarios y comentarios en los comentarios, edité el mensaje y agregué más. Tanto con y catch definen variables en sus respectivos bloques, y esta es el área de bloque. Estas variables son un alias de las propiedades de los objetos que se les pasan.

  //chrome (v8) var a = { 'test1':'test1val' } test1 // error not defined with (a) { var test1 = 'replaced' } test1 // undefined a // a.test1 = 'replaced' 

EDITAR: Ejemplo de explicación:

test1 está vinculado al bloque c, pero suavizado a a.test1. "Var test1" crea una nueva variable test1 en el contexto léxico superior (función o global), a menos que sea una propiedad a, que es.

Aplaudir Tenga cuidado al usar 'with'; al igual que var es noop, si una variable ya está definida en una función, ¡también es un noop para los nombres importados de un objeto! Un poco de heads-up sobre un nombre que ya ha sido definido lo haría mucho más seguro. Debido a esto, yo personalmente nunca lo usaré.

16
25 окт. Respuesta dada por Gerard ONeill el 25 de octubre. 2013-10-25 03:41 '13 a las 3:41 2013-10-25 03:41

Descubrí que muchas personas que no están familiarizadas con JavaScript no entienden que la herencia está disponible de forma predeterminada en el idioma y que el alcance de las posibilidades es el único. Proporcioné una extensión para el embellecedor, que escribí a fines del año pasado llamada JSPretty. La función de la función de color de la función en el código y siempre asocia el color para todas las variables declaradas en esta área. El cierre se demuestra visualmente cuando una variable con un color de un alcance se usa en otra área.

Intenta usar la función:

Vea la demostración en:

Ver el código en:

Esta función actualmente ofrece soporte para una profundidad de 16 funciones anidadas, pero actualmente no tiene variables globales de color.

9
21 марта '13 в 20:31 2013-03-21 20:31 la respuesta se da austincheney 21 de marzo de 2013 a las 20:31 2013-03-21 20:31

Para agregar a otras respuestas, el alcance es una lista de todos los identificadores declarados (variables) y se aplica un conjunto estricto de reglas con respecto a cómo están disponibles para el código actual. Esta búsqueda puede diseñarse para asignar una variable que sea un enlace LHS (lado izquierdo), o se puede usar para extraer su valor, que es un enlace RHS (derecho). Estas imágenes son lo que hace el motor de JavaScript internamente cuando compila y ejecuta el código.

Entonces, desde este punto de vista, creo que la imagen ayudará a lo que encontré en el libro Scopes and Closures Kyle Simpson:

2019

30 марта '16 в 16:33 2016-03-30 16:33 La respuesta la da James Drinkard el 30 de marzo de 2016 a las 16:33 2016-03-30 16:33

JavaScript tiene solo dos tipos de alcance:

  • Escala global Global no es más que un área de nivel de ventana. Aquí la variable está presente en toda la aplicación.
  • Área funcional . Una variable declarada dentro de una función con la palabra clave var tiene un área funcional.

Cada vez que se llama a una función, se crea un objeto de alcance de variable (y se incluye en la cadena de alcance), seguido de variables en JavaScript.

  a = "global"; function outer(){ b = "local"; console.log(a+b); //"globallocal" } outer(); 

Región de la cadena →

  • Nivel de ventana: outer funciones a y outer están en el nivel superior en la cadena de ámbitos.
  • cuando se agrega una función externa, llamada el nuevo variable scope object (e incluido en la cadena de variable scope object ), con la variable b dentro de ella.

Ahora esa variable a requerido para buscar primero la región de la variable más cercana, y si la variable no existe, entonces se mueve al siguiente objeto de cadena de variable. En este caso, es el nivel de la ventana.

8
21 сент. respuesta dada por Anshul 21 sep 2014-09-21 23:44 '14 a las 23:44 2014-09-21 23:44

Escala Global:

Las variables globales son exactamente como las estrellas globales (Jackie Chan, Nelson Mandela). Puede acceder a ellos (obtener o establecer el valor) desde cualquier parte de su aplicación. Las funciones globales son similares a los eventos globales (Año Nuevo, Navidad). Puede ejecutarlos (llamarlos) desde cualquier parte de su aplicación.

 //global variable var a = 2; //global function function b(){ console.log(a); //access global variable } 

Area local

Si estás en los Estados Unidos, puedes reconocer a Kim Kardashian, la celebridad infame (de alguna manera se las arregla para hacer tabloides). Pero las personas fuera de los Estados Unidos no la reconocen. Es una estrella local, atada a su territorio.

Las variables locales son similares a las estrellas locales. Puede acceder a ellos (obtener o establecer el valor) dentro del área. La función local es similar a los eventos locales: solo puedes actuar (celebrar) dentro de esta área. Si desea acceder a ellos desde fuera del área, obtendrá un error de referencia.

 function b(){ var d = 21; //local variable console.log(d); function dog(){ console.log(a); } dog(); //execute local function } console.log(d); //ReferenceError: dddddd is not defined 

Echa un vistazo a este artículo para una comprensión en profundidad del alcance

7
24 июня '14 в 17:12 2014-06-24 17:12 KhanSharp dio la respuesta el 24 de junio de 2014 a las 17:12 2014-06-24 17:12

ejecuta el codigo Espero que esto dé una idea del alcance.

 Name = 'global data'; document.Name = 'current document data'; (function(window,document){ var Name = 'local data'; var myObj = { Name: 'object data', f: function(){ alert(this.Name); } }; myObj.newFun = function(){ alert(this.Name); } function testFun(){ alert("Window Scope : " + window.Name + "\nLocal Scope : " + Name + "\nObject Scope : " + this.Name + "\nCurrent document Scope : " + document.Name ); } testFun.call(myObj); })(window,document); 
7
18 окт. Respuesta dada por Yeasin Abedin Siam el 18 de octubre. 2014-10-18 12:54 14 a las 12:54 2014-10-18 12:54

Js modernos, ES6 +, ' const ' y ' let '

Para cada variable que cree, debe usar el área de vista general, como la mayoría de los otros idiomas principales. var está en desuso Esto hace que su código sea más seguro y más fácil de mantener.

const debe utilizarse para el 95% de los casos . Esto hace que la variable de referencia no pueda cambiar. Las propiedades de la matriz, el objeto y el nodo DOM pueden cambiar y probablemente deberían ser const .

let следует использовать для любой переменной, ожидающей переназначения. Это включает в себя цикл for. Если вы изменили значение за пределами инициализации, используйте let .