¿Qué es el alcance léxico?


682

¿Qué es una breve introducción al alcance léxico?


89
En el podcast 58, Joel alienta preguntas como estas, ya que quiere que SO se convierta en EL lugar de respuestas, incluso si han sido respondidas en otros lugares. Esta es una pregunta válida, aunque uno podría decirlo un poco más cortés.
Ralph M. Rickenbach

55
@rahul Entiendo que es una vieja pregunta. Pero estoy seguro, incluso en 2009, SO esperaba que los solicitantes hicieran un esfuerzo básico para resolverlo. Tal como está, no muestra ningún esfuerzo en absoluto. Puede ser, ¿por eso fue rechazado por muchos?
PP

13
Es posible que el autor de la pregunta no tenga (o no tenga) fluidez en inglés al escribir esta pregunta
Martin

27
La pregunta es cortés, solo dice lo que quiere. Eres libre de responder. No hay necesidad de una política demasiado sensible aquí.
Markus Siebeneicher

25
Creo que preguntas como estas son geniales porque crea contenido para SO. OMI, a quién le importa si la pregunta no tiene esfuerzo ... las respuestas tendrán un gran contenido y eso es lo que importa en este tablero de mensajes.
Jwan622

Respuestas:


686

Los entiendo a través de ejemplos. :)

Primero, el alcance léxico (también llamado alcance estático ), en sintaxis tipo C:

void fun()
{
    int x = 5;

    void fun2()
    {
        printf("%d", x);
    }
}

Cada nivel interno puede acceder a sus niveles externos.

Hay otra forma, llamada ámbito dinámico utilizado por la primera implementación de Lisp , nuevamente en una sintaxis tipo C:

void fun()
{
    printf("%d", x);
}

void dummy1()
{
    int x = 5;

    fun();
}

void dummy2()
{
    int x = 10;

    fun();
}

Aquí funpuede acceder xen dummy1o dummy2, o xen cualquier función que llame funcon xdeclarada en él.

dummy1();

imprimirá 5,

dummy2();

imprimirá 10.

El primero se llama estático porque se puede deducir en tiempo de compilación, y el segundo se llama dinámico porque el alcance externo es dinámico y depende de la llamada en cadena de las funciones.

Encuentro el alcance estático más fácil para el ojo. La mayoría de los idiomas fueron así finalmente, incluso Lisp (puede hacer ambas cosas, ¿verdad?). El alcance dinámico es como pasar referencias de todas las variables a la función llamada.

Como ejemplo de por qué el compilador no puede deducir el alcance dinámico externo de una función, considere nuestro último ejemplo. Si escribimos algo como esto:

if(/* some condition */)
    dummy1();
else
    dummy2();

La cadena de llamadas depende de una condición de tiempo de ejecución. Si es cierto, entonces la cadena de llamadas se ve así:

dummy1 --> fun()

Si la condición es falsa:

dummy2 --> fun()

El alcance externo de funen ambos casos es la persona que llama más la persona que llama y así sucesivamente .

Solo por mencionar que el lenguaje C no permite funciones anidadas ni ámbito dinámico.


19
También me gustaría señalar un tutorial muy fácil de entender que acabo de encontrar. El ejemplo de Arak es bueno, pero puede ser demasiado corto para alguien que necesita más ejemplos (en realidad, en comparación con otros idiomas ...). Echar un vistazo. Es importante entender esto , ya que esa palabra clave nos llevará a comprender el alcance léxico. howtonode.org/what-is-this
CppLearner

99
Esta es una buena respuesta. Pero la pregunta está etiquetada con JavaScript. Por lo tanto, creo que esto no debería marcarse como la respuesta aceptada. El alcance léxico específicamente en JS es diferente
Boyang el

66
Muy buena respuesta. Gracias. @Boyang no estoy de acuerdo. No soy un codificador de Lisp, pero encontré útil el ejemplo de Lisp, ya que es un ejemplo de alcance dinámico, que no se obtiene en JS.
dudewad

44
Inicialmente, pensé que el ejemplo era un código C válido y estaba confundido acerca de si había un alcance dinámico en C. ¿Quizás el descargo de responsabilidad al final podría cambiarse antes del ejemplo del código?
Yangshun Tay

2
Esta sigue siendo una respuesta muy útil, pero creo que @Boyang es correcta. Esta respuesta se refiere al 'nivel', que está más en la línea del alcance del bloque que C tiene. JavaScript por defecto no tiene alcance de nivel de bloque, por lo que dentro de un forbucle se encuentra el problema típico. El alcance léxico para JavaScript solo está en el nivel de la función a menos que se use el ES6 leto const.
icc97

274

Probemos la definición más corta posible:

El alcance léxico define cómo se resuelven los nombres de las variables en funciones anidadas: las funciones internas contienen el alcance de las funciones principales, incluso si la función principal ha regresado .

¡Eso es todo!


21
La última parte: "incluso si la función principal ha regresado" se llama Cierre.
Juanma Menéndez

1
Entendió el alcance léxico y el cierre en una sola sesión. ¡¡Gracias!!
Mazmorra

63
var scope = "I am global";
function whatismyscope(){
   var scope = "I am just a local";
   function func() {return scope;}
   return func;
}

whatismyscope()()

El código anterior devolverá "Solo soy un local". No devolverá "Soy un global". Porque la función func () cuenta dónde se definió originalmente, que está bajo el alcance de la función whatismyscope.

No se molestará por lo que se llame (el alcance global / incluso dentro de otra función), es por eso que el valor del alcance global que soy global no se imprimirá.

Esto se denomina alcance léxico donde "las funciones se ejecutan utilizando la cadena de alcance que estaba vigente cuando se definieron ", según la Guía de definición de JavaScript.

El alcance léxico es un concepto muy muy poderoso.

Espero que esto ayude..:)


3
es una explicación muy buena, quiero agregar una cosa más si escribe la función func () {return this.scope;} luego devolverá "I am global" simplemente use esta palabra clave y su alcance cambiará
Rajesh Kumar Bhawsar

41

El alcance léxico (AKA estático) se refiere a la determinación del alcance de una variable basándose únicamente en su posición dentro del corpus textual de código. Una variable siempre se refiere a su entorno de nivel superior. Es bueno entenderlo en relación con el alcance dinámico.


41

El alcance define el área, donde las funciones, variables y demás están disponibles. La disponibilidad de una variable, por ejemplo, se define dentro de su contexto, digamos la función, archivo u objeto en el que se definen. Generalmente llamamos a estas variables locales.

La parte léxica significa que puede derivar el alcance de la lectura del código fuente.

El alcance léxico también se conoce como alcance estático.

El alcance dinámico define variables globales a las que se puede llamar o hacer referencia desde cualquier lugar después de definirse. A veces se denominan variables globales, aunque las variables globales en la mayoría de los lenguajes de programa son de alcance léxico. Esto significa que puede derivarse de la lectura del código que la variable está disponible en este contexto. Tal vez uno tiene que seguir una cláusula de usos o inclusiones para encontrar la instanciación o definición, pero el código / compilador conoce la variable en este lugar.

En el ámbito dinámico, por el contrario, primero busca en la función local, luego busca en la función que llamó a la función local, luego busca en la función que llamó a esa función, y así sucesivamente, sube la pila de llamadas. "Dinámico" se refiere al cambio, ya que la pila de llamadas puede ser diferente cada vez que se llama a una función determinada, por lo que la función puede afectar a diferentes variables dependiendo de dónde se llama. (ver aquí )

Para ver un ejemplo interesante de alcance dinámico, consulte aquí .

Para más detalles ver aquí y aquí .

Algunos ejemplos en Delphi / Object Pascal

Delphi tiene alcance léxico.

unit Main;
uses aUnit;  // makes available all variables in interface section of aUnit

interface

  var aGlobal: string; // global in the scope of all units that use Main;
  type 
    TmyClass = class
      strict private aPrivateVar: Integer; // only known by objects of this class type
                                    // lexical: within class definition, 
                                    // reserved word private   
      public aPublicVar: double;    // known to everyboday that has access to a 
                                    // object of this class type
    end;

implementation

  var aLocalGlobal: string; // known to all functions following 
                            // the definition in this unit    

end.

Lo más cercano que Delphi llega al ámbito dinámico es el par de funciones RegisterClass () / GetClass (). Para su uso ver aquí .

Digamos que el tiempo que se llama a RegisterClass ([TmyClass]) para registrar una determinada clase no se puede predecir leyendo el código (se llama en un método de clic de botón llamado por el usuario), se obtendrá el código que llama a GetClass ('TmyClass') un resultado o no La llamada a RegisterClass () no tiene que estar en el ámbito léxico de la unidad usando GetClass ();

Otra posibilidad de alcance dinámico son los métodos anónimos (cierres) en Delphi 2009, ya que conocen las variables de su función de llamada. No sigue la ruta de llamada desde allí de forma recursiva y, por lo tanto, no es completamente dinámica.


2
En realidad privado es accesible en toda la unidad donde se define la clase. Es por eso que se introdujo "Privado estricto" en D2006.
Marco van de Voort

2
+1 para lenguaje sencillo (a diferencia del lenguaje complicado y ejemplos sin mucha descripción)
Pops

36

Me encantan las respuestas completas y agnósticas del lenguaje de personas como @Arak. Sin embargo, dado que esta pregunta fue etiquetada con JavaScript , me gustaría incluir algunas notas muy específicas de este lenguaje.

En JavaScript nuestras opciones para el alcance son:

  • tal cual (sin ajuste de alcance)
  • léxico var _this = this; function callback(){ console.log(_this); }
  • Unido callback.bind(this)

Vale la pena señalar, creo, que JavaScript realmente no tiene un alcance dinámico . .bindajusta la thispalabra clave, y eso está cerca, pero técnicamente no es lo mismo.

Aquí hay un ejemplo que demuestra ambos enfoques. Hace esto cada vez que toma una decisión sobre cómo abarcar las devoluciones de llamada para que esto se aplique a las promesas, los controladores de eventos y más.

Léxico

Esto es lo que podría Lexical Scopingllamar las devoluciones de llamada en JavaScript:

var downloadManager = {
  initialize: function() {
    var _this = this; // Set up `_this` for lexical access
    $('.downloadLink').on('click', function () {
      _this.startDownload();
    });
  },
  startDownload: function(){
    this.thinking = true;
    // Request the file from the server and bind more callbacks for when it returns success or failure
  }
  //...
};

Unido

Otra forma de alcance es usar Function.prototype.bind:

var downloadManager = {
  initialize: function() {
    $('.downloadLink').on('click', function () {
      this.startDownload();
    }.bind(this)); // Create a function object bound to `this`
  }
//...

Estos métodos son, hasta donde yo sé, conductualmente equivalentes.


El uso bindno afecta el alcance.
Ben Aston

12

Ámbito léxico: las variables declaradas fuera de una función son variables globales y son visibles en todas partes en un programa JavaScript. Las variables declaradas dentro de una función tienen alcance de función y son visibles solo para el código que aparece dentro de esa función.


12

IBM lo define como:

La parte de un programa o unidad de segmento en la que se aplica una declaración. Se conoce un identificador declarado en una rutina dentro de esa rutina y dentro de todas las rutinas anidadas. Si una rutina anidada declara un elemento con el mismo nombre, el elemento externo no está disponible en la rutina anidada.

Ejemplo 1:

function x() {
    /*
    Variable 'a' is only available to function 'x' and function 'y'.
    In other words the area defined by 'x' is the lexical scope of
    variable 'a'
    */
    var a = "I am a";

    function y() {
        console.log( a )
    }
    y();

}
// outputs 'I am a'
x();

Ejemplo 2

function x() {

    var a = "I am a";

    function y() {
         /*
         If a nested routine declares an item with the same name,
         the outer item is not available in the nested routine.
         */
        var a = 'I am inner a';
        console.log( a )
    }
    y();

}
// outputs 'I am inner a'
x();

8

El alcance léxico significa que en un grupo anidado de funciones, las funciones internas tienen acceso a las variables y otros recursos de su alcance principal . Esto significa que las funciones secundarias están vinculadas léxicamente al contexto de ejecución de sus padres. El alcance léxico a veces también se conoce como alcance estático .

function grandfather() {
    var name = 'Hammad';
    // 'likes' is not accessible here
    function parent() {
        // 'name' is accessible here
        // 'likes' is not accessible here
        function child() {
            // Innermost level of the scope chain
            // 'name' is also accessible here
            var likes = 'Coding';
        }
    }
}

Lo que notará sobre el alcance léxico es que funciona hacia adelante, lo que significa que los contextos de ejecución de sus hijos pueden acceder al nombre. Pero no funciona hacia atrás para sus padres, lo que significa que sus padres likesno pueden acceder a la variable .

Esto también nos dice que las variables que tienen el mismo nombre en diferentes contextos de ejecución ganan prioridad de arriba a abajo de la pila de ejecución. Una variable, que tiene un nombre similar a otra variable, en la función más interna (contexto superior de la pila de ejecución) tendrá mayor prioridad.

Tenga en cuenta que esto se toma desde aquí .


8

En un lenguaje simple, el alcance léxico es una variable definida fuera de su alcance o el alcance superior está disponible automáticamente dentro de su alcance, lo que significa que no necesita pasarlo allí.

Ejemplo:

let str="JavaScript";

const myFun = () => {
    console.log(str);
}

myFun();

// Salida: JavaScript


2
La respuesta más corta y la mejor para mí con un ejemplo. Se podría haber agregado que las funciones de flecha del ES6 resuelven el problema bind. Con ellos, bindya no se requiere. Para obtener más información sobre este cambio, consulte stackoverflow.com/a/34361380/11127383
Daniel Danielecki

4

Falta una parte importante de la conversación sobre el alcance dinámico y léxico : una explicación simple de la vida útil de la variable de alcance, o cuándo se puede acceder a la variable.

El alcance dinámico solo se corresponde con el alcance "global" en la forma en que tradicionalmente lo pensamos (la razón por la que menciono la comparación entre ambos es que ya se ha mencionado , y no me gusta particularmente la explicación del artículo vinculado ); probablemente sea mejor que no hagamos la comparación entre global y dinámico, aunque supuestamente, según el artículo vinculado, "... [es] útil como un sustituto de las variables de alcance global".

Entonces, en inglés simple, ¿cuál es la distinción importante entre los dos mecanismos de alcance?

El alcance léxico se ha definido muy bien en todas las respuestas anteriores: las variables con alcance léxico están disponibles, o son accesibles, en el nivel local de la función en la que se definió.

Sin embargo, como no es el foco del OP, el alcance dinámico no ha recibido mucha atención y la atención que ha recibido significa que probablemente necesite un poco más (eso no es una crítica de otras respuestas, sino más bien un "oh, esa respuesta nos hizo desear que hubiera un poco más "). Entonces, aquí hay un poco más:

El alcance dinámico significa que el programa más grande puede acceder a una variable durante la vida útil de la llamada a la función, o mientras la función se está ejecutando. Realmente, Wikipedia realmente hace un buen trabajo con la explicación de la diferencia entre los dos. Para no ofuscarlo, aquí está el texto que describe el alcance dinámico:

... [I] n ámbito dinámico (o ámbito dinámico), si el ámbito de un nombre de variable es una función determinada, entonces su ámbito es el período de tiempo durante el cual la función se está ejecutando: mientras la función se está ejecutando, el nombre de la variable existe , y está vinculado a su variable, pero una vez que la función vuelve, el nombre de la variable no existe.


3

El alcance léxico significa que una función busca variables en el contexto en el que se definió, y no en el alcance inmediatamente a su alrededor.

Mire cómo funciona el alcance léxico en Lisp si desea más detalles. La respuesta seleccionada por Kyle Cronin en variables dinámicas y léxicas en Common Lisp es mucho más clara que las respuestas aquí.

Casualmente, solo aprendí sobre esto en una clase de Lisp, y sucede que también se aplica en JavaScript.

Ejecuté este código en la consola de Chrome.

// JavaScript               Equivalent Lisp
var x = 5;                //(setf x 5)
console.debug(x);         //(print x)
function print_x(){       //(defun print-x ()
    console.debug(x);     //    (print x)
}                         //)
(function(){              //(let
    var x = 10;           //    ((x 10))
    console.debug(x);     //    (print x)
    print_x();            //    (print-x)
})();                     //)

Salida:

5
10
5

3

Un alcance léxico en JavaScript significa que una variable definida fuera de una función puede ser accesible dentro de otra función definida después de la declaración de la variable. Pero lo contrario no es cierto; las variables definidas dentro de una función no serán accesibles fuera de esa función.

Este concepto se usa mucho en cierres en JavaScript.

Digamos que tenemos el siguiente código.

var x = 2;
var add = function() {
    var y = 1;
    return x + y;
};

Ahora, cuando llame a add () -> esto imprimirá 3.

Entonces, la función add () está accediendo a la variable global xque se define antes de la función add del método. Esto se llama debido al alcance léxico en JavaScript.


Tenga en cuenta que el fragmento de código era para un lenguaje de ámbito dinámico. Si la add()función se llamara inmediatamente después del fragmento de código dado, también se imprimiría 3. El alcance léxico no significa simplemente que una función pueda acceder a variables globales fuera del contexto local. Entonces, el código de ejemplo realmente no ayuda a mostrar lo que significa el alcance léxico. Mostrar el alcance léxico en el código realmente necesita un contraejemplo o al menos una explicación de otras posibles interpretaciones del código.
C Perkins

2

El alcance léxico se refiere al léxico de identificadores (por ejemplo, variables, funciones, etc.) visibles desde la posición actual en la pila de ejecución.

- global execution context
    - foo
    - bar
    - function1 execution context
        - foo2
        - bar2
        - function2 execution context
            - foo3
            - bar3

fooy barsiempre están dentro del léxico de los identificadores disponibles porque son globales.

Cuando function1se ejecuta, tiene acceso a un léxico de foo2, bar2, foo, y bar.

Cuando function2se ejecuta, tiene acceso a un léxico de foo3, bar3, foo2, bar2, foo, y bar.

La razón por la que las funciones globales y / o externas no tienen acceso a los identificadores de funciones internas es porque la ejecución de esa función aún no se ha producido y, por lo tanto, ninguno de sus identificadores se ha asignado a la memoria. Además, una vez que se ejecuta ese contexto interno, se elimina de la pila de ejecución, lo que significa que todos sus identificadores se han recolectado basura y ya no están disponibles.

Finalmente, esta es la razón por la cual un contexto de ejecución anidado SIEMPRE puede acceder al contexto de ejecución de sus antepasados ​​y, por lo tanto, tiene acceso a un léxico mayor de identificadores.

Ver:

Un agradecimiento especial a @ robr3rd por ayudarnos a simplificar la definición anterior.


1

Aquí hay un ángulo diferente sobre esta cuestión que podemos obtener dando un paso atrás y observando el papel del alcance en el marco de interpretación más amplio (ejecutar un programa). En otras palabras, imagine que está construyendo un intérprete (o compilador) para un idioma y que es responsable de calcular la salida, dado un programa y algunas entradas.

La interpretación implica hacer un seguimiento de tres cosas:

  1. Estado: es decir, variables y ubicaciones de memoria referenciadas en el montón y la pila.

  2. Operaciones en ese estado, es decir, cada línea de código en su programa

  3. El entorno en el que se ejecuta una operación determinada , es decir, la proyección de estado en una operación.

Un intérprete comienza en la primera línea de código de un programa, calcula su entorno, ejecuta la línea en ese entorno y captura su efecto en el estado del programa. Luego sigue el flujo de control del programa para ejecutar la siguiente línea de código y repite el proceso hasta que finaliza el programa.

La forma de calcular el entorno para cualquier operación es a través de un conjunto formal de reglas definidas por el lenguaje de programación. El término "enlace" se usa con frecuencia para describir la asignación del estado general del programa a un valor en el entorno. Tenga en cuenta que por "estado general" no nos referimos al estado global, sino a la suma total de cada definición accesible, en cualquier punto de la ejecución).

Este es el marco en el que se define el problema de alcance. Ahora a la siguiente parte de cuáles son nuestras opciones.

  • Como implementador del intérprete, puede simplificar su tarea haciendo que el entorno sea lo más cercano posible al estado del programa. En consecuencia, el entorno de una línea de código simplemente se definiría por el entorno de la línea de código anterior con los efectos de esa operación aplicada, independientemente de si la línea anterior era una asignación, una llamada a función, el retorno de una función, o una estructura de control como un bucle while.

Esta es la esencia del alcance dinámico , en el que el entorno en el que se ejecuta cualquier código está vinculado al estado del programa según lo definido por su contexto de ejecución.

  • O bien , podría pensar en un programador que use su lenguaje y simplifique su tarea de realizar un seguimiento de los valores que puede tomar una variable. Hay demasiados caminos y demasiada complejidad involucrados en el razonamiento sobre el resultado de la totalidad de la ejecución pasada. El alcance léxico ayuda a hacer esto al restringir el entorno actual a la porción de estado definida en el bloque actual, función u otra unidad de alcance, y su padre (es decir, el bloque que encierra el reloj actual o la función que llamó a la función actual).

En otras palabras, con el alcance léxico, el entorno que ve cualquier código está vinculado al estado asociado con un alcance definido explícitamente en el lenguaje, como un bloque o una función.


0

Antigua pregunta, pero aquí está mi opinión al respecto.

El alcance léxico (estático) se refiere al alcance de una variable en el código fuente .

En un lenguaje como JavaScript, donde las funciones se pueden pasar y adjuntar y volver a adjuntar a objetos diversos, es posible que ese alcance dependa de quién llama a la función en ese momento, pero no es así. Cambiar el alcance de esa manera sería un alcance dinámico, y JavaScript no lo hace, excepto posiblemente con la thisreferencia del objeto.

Para ilustrar el punto:

var a='apple';

function doit() {
    var a='aardvark';
    return function() {
        alert(a);
    }
}

var test=doit();
test();

En el ejemplo, la variable ase define globalmente, pero está sombreada en la doit()función. Esta función devuelve otra función que, como puede ver, se basa en la avariable fuera de su propio alcance.

Si ejecuta esto, encontrará que el valor utilizado aardvarkno es el appleque, aunque está dentro del alcance de la test()función, no está dentro del alcance léxico de la función original. Es decir, el alcance utilizado es el alcance tal como aparece en el código fuente, no el alcance donde se usa realmente la función.

Este hecho puede tener consecuencias molestas. Por ejemplo, puede decidir que es más fácil organizar sus funciones por separado y luego usarlas cuando llegue el momento, como en un controlador de eventos:

var a='apple',b='banana';

function init() {
  var a='aardvark',b='bandicoot';
  document.querySelector('button#a').onclick=function(event) {
    alert(a);
  }
  document.querySelector('button#b').onclick=doB;
}

function doB(event) {
  alert(b);
}

init();
<button id="a">A</button>
<button id="b">B</button>

Este ejemplo de código hace uno de cada uno. Puede ver que debido al alcance léxico, el botón Ausa la variable interna, mientras que el botón Bno. Puede terminar anidando funciones más de lo que le hubiera gustado.

Por cierto, en ambos ejemplos, también notará que las variables de ámbito léxico interno persisten a pesar de que la función de función que contiene ha seguido su curso. Esto se llama cierre y se refiere al acceso de una función anidada a variables externas, incluso si la función externa ha finalizado. JavaScript debe ser lo suficientemente inteligente como para determinar si esas variables ya no son necesarias, y si no, puede recolectar basura.


-1

Normalmente aprendo con el ejemplo, y aquí hay algo:

const lives = 0;

function catCircus () {
    this.lives = 1;
    const lives = 2;

    const cat1 = {
        lives: 5,
        jumps: () => {
            console.log(this.lives);
        }
    };
    cat1.jumps(); // 1
    console.log(cat1); // { lives: 5, jumps: [Function: jumps] }

    const cat2 = {
        lives: 5,
        jumps: () => {
            console.log(lives);
        }
    };
    cat2.jumps(); // 2
    console.log(cat2); // { lives: 5, jumps: [Function: jumps] }

    const cat3 = {
        lives: 5,
        jumps: () => {
            const lives = 3;
            console.log(lives);
        }
    };
    cat3.jumps(); // 3
    console.log(cat3); // { lives: 5, jumps: [Function: jumps] }

    const cat4 = {
        lives: 5,
        jumps: function () {
            console.log(lives);
        }
    };
    cat4.jumps(); // 2
    console.log(cat4); // { lives: 5, jumps: [Function: jumps] }

    const cat5 = {
        lives: 5,
        jumps: function () {
            var lives = 4;
            console.log(lives);
        }
    };
    cat5.jumps(); // 4
    console.log(cat5); // { lives: 5, jumps: [Function: jumps] }

    const cat6 = {
        lives: 5,
        jumps: function () {
            console.log(this.lives);
        }
    };
    cat6.jumps(); // 5
    console.log(cat6); // { lives: 5, jumps: [Function: jumps] }

    const cat7 = {
        lives: 5,
        jumps: function thrownOutOfWindow () {
            console.log(this.lives);
        }
    };
    cat7.jumps(); // 5
    console.log(cat7); // { lives: 5, jumps: [Function: thrownOutOfWindow] }
}

catCircus();

-1

Este tema está estrechamente relacionado con la bindfunción incorporada e introducido en ECMAScript 6 Funciones de flecha . Fue realmente molesto, porque para cada nuevo método de "clase" (función en realidad) que queríamos usar, teníamos que hacerlo bindpara tener acceso al alcance.

JavaScript por defecto no establece su alcance de thisfunciones (no establece el contexto en this). Por defecto, debe decir explícitamente qué contexto desea tener.

Las funciones de flecha obtienen automáticamente el llamado alcance léxico (tienen acceso a la definición de la variable en su bloque contenedor). Cuando se utilizan funciones de flecha, se une automáticamente thisal lugar donde se definió la función de flecha en primer lugar, y el contexto de estas funciones de flecha es su bloque contenedor.

Vea cómo funciona en la práctica en los ejemplos más simples a continuación.

Antes de las funciones de flecha (sin alcance léxico por defecto):

const programming = {
  language: "JavaScript",
  getLanguage: function() {
    return this.language;
  }
}

const globalScope = programming.getLanguage;
console.log(globalScope()); // Output: undefined

const localScope = programming.getLanguage.bind(programming);
console.log(localScope()); // Output: "JavaScript"

Con funciones de flecha (alcance léxico por defecto):

const programming = {
  language: "JavaScript",
  getLanguage: function() {
    return this.language;
  }
}

const arrowFunction = () => {
    console.log(programming.getLanguage());
}

arrowFunction(); // Output: "JavaScript"
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.