Как получить данные из обратного вызова без использования глобальной переменной? - PullRequest
1 голос
/ 02 апреля 2020

Ниже я создал упрощенную версию своего кода.

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++;
    }
}

Как мне избавиться от глобальной переменной перевода? Есть ли способ обновить переменную, основанную на событии, без использования глобальной переменной?

Ответы [ 2 ]

3 голосов
/ 02 апреля 2020

Я не очень хорошо говорю по-английски sh, но попробую.

Переменная translation находится в хорошем месте, если вы хотите, чтобы эта переменная не была доступна извне. Вы можете создать IIFE для создания области.

(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++;
        }
    }
})();

1 голос
/ 02 апреля 2020

Как отмечает Nik020, вы можете использовать закрытие. Выражение немедленного вызова функции (IIFE) создает замыкание, но оно не обязательно должно быть шаблоном IIFE. Обычная именованная функция будет делать то же самое

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();

Шаблон IIFE просто означает, что вам не нужно придумывать имя, и имя не будет конфликтовать с другими именами.

Вы Можно также связать this. Пример

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();

Вы используете функции стрелки, которые являются syntacti c sugar для привязки 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();

Если вы хотите иметь возможность удалить слушателя, и вы используете функцию стрелки или привязку вы можете сохранить ссылку на функцию в переменной

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();

Существует еще 4-10 способов связать это и / или сделать замыкание .

...