【问题标题】:How do I get data out of a callback without using a global variable?如何在不使用全局变量的情况下从回调中获取数据?
【发布时间】:2020-04-02 17:24:13
【问题描述】:

我在下面创建了我的代码的简化版本。

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

我怎样才能摆脱翻译全局变量?有没有办法在不使用全局变量的情况下根据事件更新变量?

【问题讨论】:

  • 将所有内容包装在一个 IIFE 中。在这种情况下,您不能替换外部范围变量,但它不必是全局变量。

标签: javascript callback closures addeventlistener


【解决方案1】:

我的英语不太好,但我会努力的。

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

【讨论】:

  • 供 user1801359 参考:IIFE = 立即调用函数表达式
【解决方案2】:

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

您使用箭头函数作为绑定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();

bind this 和/或make a closure 还有 4 到 10 种方法。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-21
    • 2021-03-17
    • 2019-10-02
    • 1970-01-01
    相关资源
    最近更新 更多