Problem Variable range in JavaScript

3

I have a very strange variable scope problem, I am using the setInterval () function and there is a variable that has no scope in this function.

this is my code:

cantidad = 14;    
nItemCart= 14;
interval=[];
restarCantidad(cantidad, nItemCart){
    if (cantidad > 0) {
      cantidad--;
      this.nItemCart--;

      console.log("estoy restando", cantidad, this.nItemCart); // en esta linea si reconoce la variable
      this.interval.push(setInterval(function (nItemCart) {
        if (cantidad > 0) {
          cantidad--;
          console.log(nItemCart, this.nItemCart); // en esta linea no reconoce la variable
          nItemCart--;
          console.log("estoy restando", cantidad, nItemCart, this.nItemCart); // en esta otra linea tampoco reconoce la variable
        }
      }, 150));
    }


this.restarCantidad(this.cantidad, this.nItemCart);

the result by console is as follows:

estoy restando 13 13
undefined NaN
estoy restando 12 NaN NaN
undefined NaN
estoy restando 11 NaN NaN
undefined NaN
estoy restando 10 NaN NaN
undefined NaN
estoy restando 9 NaN NaN
undefined NaN
estoy restando 8 NaN NaN
undefined NaN
estoy restando 7 NaN NaN
undefined NaN
estoy restando 6 NaN NaN
undefined NaN
estoy restando 5 NaN NaN
undefined NaN
estoy restando 4 NaN NaN
undefined NaN
estoy restando 3 NaN NaN
undefined NaN
estoy restando 2 NaN NaN
undefined NaN
estoy restando 1 NaN NaN
undefined NaN
estoy restando 0 NaN NaN
    
asked by Daniel Enrique Rodriguez Caste 07.07.2017 в 18:57
source

4 answers

1

As I mentioned in my comments, you can solve it by using a temporary variable in this way before function push :

cantidad = 14;    
nItemCart= 14;
interval=[];
restarCantidad(cantidad, nItemCart){
    if (cantidad > 0) {
      cantidad--;
      this.nItemCart--;

      console.log("estoy restando", cantidad, this.nItemCart);

      var self = this;

      this.interval.push(setInterval(function (nItemCart) {
        if (cantidad > 0) {
          cantidad--;
          console.log(nItemCart, self.nItemCart);
          nItemCart--;
          console.log("estoy restando", cantidad, nItemCart, self.nItemCart);
        }
      }, 150));
    }


this.restarCantidad(this.cantidad, this.nItemCart);

As you can see, this is a scope problem, the use of this changes when you use it within the function this.interval.push(...) and to be able to refer to the variables outside this function I have defined self .

    
answered by 26.08.2017 / 00:56
source
1

I execute all answers and none of them work, I still get the error of NaN and undefined .

What really happens is that you have defined the variable nItemCart 3 times and in a different context.

For example:

this.interval.push(setInterval(function (nItemCart) { 
    //... 
})

You never pass the value of all callback for the parameter nItemCart to the function setInterval . It should be like this:

   var nItemCart = 9;
setInterval(function(){console.log(arguments)},300, nItemCart);

After this:

this.interval.push(setInterval(function (nItemCart) {  
    this.nItemCart
    //..
})

this in this case refers to the current context in which the function is executed, not the parameter, so it will give you undefined .

This would be the final result

cantidad = 5;    
nItemCart= 5;
interval=[];
function restarCantidad(cantidad, nItemCart){
    if (cantidad > 0) {
      cantidad--;
      this.nItemCart--;

      console.log("estoy restando", cantidad, nItemCart); // en esta linea si reconoce la variable
      this.interval.push(setInterval(function (nItemCart) {
        if (cantidad > 0) {
          cantidad--;
          console.log(nItemCart, nItemCart); // en esta linea no reconoce la variable
          nItemCart--;
          console.log("estoy restando", cantidad, nItemCart, this.nItemCart); // en esta otra linea tampoco reconoce la variable
        }
      }, 150, nItemCart));
    }
}

this.restarCantidad(this.cantidad, this.nItemCart);
    
answered by 07.07.2017 в 21:01
0

The problem is this (all) or that seems because of what little you put. Remove the this from the anonymous function, I would tell you to remove all but I do not know the rest of the code

cantidad = 14;    
nItemCart= 14; //No tiene el this, se maneja como variable local no como propiedad
interval=[]; //No tiene el this, se maneja como variable local no como propiedad

//Esta funcion no tiene el this entonces esta dentro de un contexto global
restarCantidad(cantidad, nItemCart){
    if (cantidad > 0) {
      cantidad--;

      //El this hace referencia al contexto de restarCantidad
      //La variable nItemCart que le pasas como argumento será distinta a ésta aunque tengan el mismo nombre
      this.nItemCart--; 

      //Lo mismo, el this hace referencia al contexto de restarCantidad, la variable que le pasas como asgumento será distinta
      console.log("estoy restando", cantidad, this.nItemCart); 
      //El this.interval no es el mismo que declaraste fuera de la funcion ya que el this hace referencia al contexto de restarCantidad
      this.interval.push(setInterval(function (nItemCart) { //<- Esto es una función anónima*
        if (cantidad > 0) {
          cantidad--;
          //El this de this.nItemCart hace referencia al contexto de la función anónima* creada en el setInterval
          console.log(nItemCart, this.nItemCart); 
          nItemCart--;
          //Lo mismo, el this hace referencia al contexto de la función anónima
          console.log("estoy restando", cantidad, nItemCart, this.nItemCart); // en esta otra linea tampoco reconoce la variable
        }
      }, 150));
    }

//Como no está el código completo no se el this a quien hace referencia 
//pero es diferente al restarCantidad de arriba, ya que el de arriba no tiene un this entonces su contexto es el global
this.restarCantidad(this.cantidad, this.nItemCart);

EDITO That was not the solution it was because your code did not work Correcting it would be like this

cantidad = 14;    
nItemCart= 14; //No tiene el this, se maneja como variable local no como propiedad
interval=[]; //No tiene el this, se maneja como variable local no como propiedad

//Esta funcion no tiene el this entonces esta dentro de un contexto global
function restarCantidad(){
    if (cantidad > 0) {
      cantidad--;  

      //El this hace referencia al contexto de restarCantidad
      //La variable nItemCart que le pasas como argumento será distinta a ésta aunque tengan el mismo nombre
      nItemCart--; 

      //Lo mismo, el this hace referencia al contexto de restarCantidad, la variable que le pasas como asgumento será distinta
      console.log("estoy restando", cantidad, nItemCart); 
      //El this.interval no es el mismo que declaraste fuera de la funcion ya que el this hace referencia al contexto de restarCantidad
      this.interval.push(setInterval(function () { //<- Esto es una función anónima*
        if (cantidad > 0) {
          cantidad--;
          //El this de this.nItemCart hace referencia al contexto de la función anónima* creada en el setInterval
          console.log(nItemCart, nItemCart); 
          nItemCart--;
          //Lo mismo, el this hace referencia al contexto de la función anónima
          console.log("estoy restando", cantidad, nItemCart, nItemCart); // en esta otra linea tampoco reconoce la variable
        }
      }, 150));
    }
}
//Como no está el código completo no se el this a quien hace referencia 
//pero es diferente al restarCantidad de arriba, ya que el de arriba no tiene un this entonces su contexto es el global
restarCantidad(); 
    
answered by 07.07.2017 в 19:59
0

Your problem is a problem of concept, this refers to the area that uses it, for example, in your case this exists only in the scope of each function, I explain:

cantidad = 14;    
nItemCart= 14;
interval=[];
restarCantidad(cantidad, nItemCart){
    if (cantidad > 0) {
      cantidad--;
      this.nItemCart--; //*** Aquí estas usando this para referirte al ambito de la funcion "restarCantidad" hasta el momento todo correcto

      console.log("estoy restando", cantidad, this.nItemCart); // en esta linea si reconoce la variable
      this.interval.push(setInterval(function (nItemCart) {
        if (cantidad > 0) {
          cantidad--;
    //Como ves, la funcion "this.interval.pus" usa un "callback" que es una función anonima, 
//es decir otra función. por lo tanto tiene un ambito propio, esto quiere decir que cuando usas "this" aquí dentro, solo usa el ambito de la función. por eso "this.nItemCart" es diferente al que usas arriba.
          console.log(nItemCart, this.nItemCart); 
          nItemCart--;
          console.log("estoy restando", cantidad, nItemCart, this.nItemCart); // en esta otra linea tampoco reconoce la variable
        }
      }, 150));
    }


this.restarCantidad(this.cantidad, this.nItemCart);

I'll explain it to you with a simpler example.

// función sencilla que recibe una variable a
function funcion1(a){
    // Declaras una variable dentro de la función.
    let variable = 10;

    // imprimo el valor de la variable, en este caso "this" hace referencia al ambito de la función "funcion1";
    console.log(this.variable); //Imprime 10

    setTimeout(function(){
      let variable = 30;
      // imprimo el valor de la variable, en este caso "this" hace referencia al ambito de la función anónima del "SetTimeout"
      console.log(this.variable);   //imprime 30;    
    },1000);

    // otra forma para poder enteder mejor, cuando se llama a funcion2 se crea un ambito solo para esa funcion y es la que usa el "this":
    setTimeout(funcion2 ,1000);

}

// funcion sencilla que se llama desde el "setTimeout"
function funcion2(){
  let variable = 50;
  // imprimo el valor de la variable, en este caso "this" hace referencia al ambito de la función funcion2
  console.log(this.variable);   //imprime 50;    
}

Now I propose the way you could work:

//Aquí estas declarando las variables de forma global (a menos que este código esté dentro de alguna funcion o clase);
// Esto queire decir que se puede acceder a estas variables desde caulquier función.
    cantidad = 14;    
    nItemCart= 14;
    interval=[];


    // Según entiendo, intentas modificar las variables definidas arriba, por eso no creo necesario que las pases como parametro
    // Ya que como expliqué arriba se pueden acceder desde cualquier función.

    function restarCantidad(){
        if (cantidad > 0) {
          cantidad--;
          // no necesitamos usar el "this";
          nItemCart--;

          console.log("estoy restando", cantidad, nItemCart); // No usamos el "this"
          interval.push(setInterval(function () { // no recibe parametros
            if (cantidad > 0) {
              cantidad--;
              console.log(nItemCart, nItemCart);  //No usamos el "this"
              nItemCart--;
              console.log("estoy restando", cantidad, nItemCart, nItemCart); // sin el "this";
            }
          }, 1500));
        }
}


    // LLalamos la funcion sin parametros.
    this.restarCantidad();

If you want to understand a little more about the context of the functions, I leave you some documentation so that you put it into practice

link

    
answered by 07.07.2017 в 20:22