【问题标题】:How to pass current scope to a function reference?如何将当前范围传递给函数引用?
【发布时间】:2019-05-12 11:40:45
【问题描述】:

我有以下代码构造一个字符串并将一个事件添加到一个显示所述字符串的按钮:

function initEvents() {
  const message = processSomeString();
  myButton.addEventListener( () => {
    //Some other code
    alert(message);
  })
}

上述方法之所以有效,是因为在内存中,任意事件函数与其外部作用域一起存储。

我想删除嵌套匿名函数以提高可读性,但是如何将message 变量附加到引用函数?

考虑到 ES6+,最好采用现代方式

Function.prototype.bind() 并不理想,因为我需要 this 引用不改变我的实际上下文。

function initEvents () {
  const message = processSomeString();
  myButton.addEventListener(myButtonClick);
}

function myButtonClick () {
  //Some other code
  alert(message??);
}

【问题讨论】:

  • “去掉嵌套的匿名函数以提高可读性”...但是当你发现其他选项的可读性较少时,你还会想要吗?
  • @spender 不,但我需要先知道其他选项:P
  • 为了最大的可读性,我可能会:myButton.addEventListener( () => callSomeMethodWith(message) )

标签: javascript optimization ecmascript-6 readability


【解决方案1】:

使用.bind:

function initEvents () {
  const message = 'any string' //processSomeString();
  
  // pass `myButton` as first argument of `.bind`
  // so that in your `myButtonClick()` you still have reference to `this`
  myButton.addEventListener('click', myButtonClick.bind(myButton, message));
}

function myButtonClick(message, e){
  console.log(`this: ${this}`);
  console.log(`message: ${message}`);
}

initEvents();
<button id="myButton">Button</button>

请注意,在您的代码中,这行:myButton.addEventListener(myButtonClick) 将不起作用,因为您缺少一个用于 .addEventListener"eventType" argument

编辑以适应问题:

要保留this 关键字引用,只需将this 作为第一个参数传递:

function initEvents () {
  const message = 'any string' //processSomeString();

  // For JS beginners, just read the documentation link above for explanation
  myButton.addEventListener('click', myButtonClick.bind(this, message));
}

function myButtonClick(message, e){
  console.log(`this: ${this}`);
  console.log(`message: ${message}`);
}

initEvents();
<button id="myButton">Button</button>

【讨论】:

  • OP 想要保留 this 上下文...
  • 是的,我不确定是我也忽略了它还是后来添加的......
【解决方案2】:

你不能传递范围,你需要传递参数

function myButtonClick(message) {
  //Some other code
  alert(message);
}

function initEvents() {
  const message = processSomeString();

  myButton.addEventListener(() => myButtonClick.call(this, message));
  // or:
  myButton.addEventListener(myButtonClick.bind(this, message));
}

请注意,我觉得在这里保留this 很奇怪。这只有在两个函数都是同一个对象上的方法时才有意义,在这种情况下.bind(this) 是一个常见的习惯用法。如果它们是不相关的函数,那么以这种方式传递 this 上下文是……意想不到的。

【讨论】:

  • 你会推荐哪个?我个人不喜欢使用 .bind,但匿名函数只是将参数传递给另一个函数并不会提高可读性。
  • 它们实际上是同一个对象的方法,我只是懒得把所有的东西都放在例子中。
  • 那么唯一的另一个选择是...addEventListener(() => this.myButtonClick(message))。无论您喜欢那个还是bind 都是一个品味问题。
  • 是的,我认为这是最好的解决方案,不仅味道好,而且在某些情况下它更安全
猜你喜欢
  • 1970-01-01
  • 2013-03-08
  • 1970-01-01
  • 1970-01-01
  • 2021-06-10
  • 2013-08-17
  • 2016-01-14
  • 1970-01-01
  • 2022-10-04
相关资源
最近更新 更多