1

I created a simplified version of my code below.

var translation = 0;

function main() {
    // load images

    loopClosure(images);
}

function loopClosure(images) {
    // setup webgl

    function render() {
        window.requestAnimationFrame(render);

        // use translation here to update image locations
    }

    render();
}

document.addEventListener('keydown', keyboardHandler, false);

function keyboardHandler(event) {
    if (event.key == 'ArrowLeft') {
        translation--;
    }
    if (event.key == 'ArrowRight') {
        translation++;
    }
}

How can I get rid of the translation global variable? Is there a way to update a variable based on an event without using a global variable?

gman
  • 83,286
  • 25
  • 191
  • 301
user1801359
  • 251
  • 1
  • 2
  • 9
  • 2
    Wrap everything within an IIFE. You can't replace the outer scope variable in this case, but that doesn't have to be a global variable. – Teemu Apr 02 '20 at 17:29

2 Answers2

3

I don't speak english very well, but I'll try.

The var translation is in a good place, if you want this variable cannot be accessed from outside. you can create IIFE for create scope.

(function () { 
    var translation = 0;

    function main() {
        // load images

        loopClosure(images);
    }

    function loopClosure(images) {
        // setup webgl

        function render() {
            window.requestAnimationFrame(render);

            // use translation here to update image locations
        }

        render();
    }

    document.addEventListener('keydown', keyboardHandler, false);

    function keyboardHandler(event) {
        if (event.key == 'ArrowLeft') {
            translation--;
        }
        if (event.key == 'ArrowRight') {
            translation++;
        }
    }
})();

Nik020
  • 404
  • 1
  • 6
1

As Nik020 points out you can use a closure. An Immediately Invoked Function Expression (IIFE) creates a closure but it doesn't have to be the IIFE pattern. A normal named function will do the same thing

function main() { 
    var translation = 0;

    function main() {
        // load images

        loopClosure(images);
    }

    function loopClosure(images) {
        // setup webgl

        function render() {
            window.requestAnimationFrame(render);

            // use translation here to update image locations
        }

        render();
    }

    document.addEventListener('keydown', keyboardHandler, false);

    function keyboardHandler(event) {
        if (event.key == 'ArrowLeft') {
            translation--;
        }
        if (event.key == 'ArrowRight') {
            translation++;
        }
    }
}

main();

The IIFE pattern just means you don't have to think up a name and the name will not conflict with other names.

You can also bind this. Example

class App {
  constructor() {
    this.translation = 0;
    document.addEventListener('keydown', this.keyboardHandler.bind(this), false);
  }
  keyboardHandler(event) {
    if (event.key == 'ArrowLeft') {
        this.translation--;
    }
    if (event.key == 'ArrowRight') {
        this.translation++;
    }
  }
}

const app = new App();

You use arrow functions which are syntactic sugar for binding this

class App {
  constructor() {
    this.translation = 0;
    document.addEventListener('keydown', (event) => {
      if (event.key == 'ArrowLeft') {
          this.translation--;
      }
      if (event.key == 'ArrowRight') {
          this.translation++;
      }
    }, false);
  }
}

const app = new App();

If you want to be able to remove the listener and you're using an arrow function or a bind you can store the function reference in a variable

class App {
  constructor() {
    this.translation = 0;
    const keyboardHandler = (event) => {
      if (event.key == 'ArrowLeft') {
          this.translation--;
      }
      if (event.key == 'ArrowRight') {
          this.translation++;
      }
    };
    document.addEventListener('keydown', keyboardHandler, false);
  }
}

const app = new App();

There's 4 to 10 more ways to bind this and/or make a closure.

gman
  • 83,286
  • 25
  • 191
  • 301