如何防止在ES6中覆盖上下文

时间:2016-01-05 23:42:01

标签: javascript jquery javascript-events this ecmascript-6

How to prevent jquery to override "this"非常相似,但在ES6中。

这是我的班级:

class FeedbackForm {
  constructor(formEl) {
    this.$form = $(formEl)
    this.$form.submit(this.sendStuff)

    this.alerts = $('#something');
  }

  /**
   * Sends the feedback
   * @param {Event} e
   */
  sendStuff(e) {
    e.preventDefault()

    if (this.alerts.length) {
      window.alert('Notice... stuff')
    }

    $.ajax({
      type: this.$form.prop('method'),
      url: this.$form.prop('action'),
      data: this.$form.serialize()
    }).done(() => window.location.reload(true))
  }
}

sendStuff方法是表单的事件处理程序,jQuery使用Function.prototype.apply调用它。我相信。因此,this内的sendStuff会被jQuery应用的事件目标覆盖,我无法访问this.alerts或任何其他属性方法。

我不确定我是否可以在此处应用var that = this技巧或如何解决此问题?

3 个答案:

答案 0 :(得分:1)

您可以使用符号将$(document).on('load', ... 实例与表单元素相关联。

然后,在事件监听器中,parseInt()FeedbackForm将成为表单元素。使用该符号可以检索this实例。

e.currentTarget
FeedbackForm

限制是您不能将相同的表单元素与不同的const myFeedbackForm = Symbol(); class FeedbackForm { constructor(formEl) { formEl[myFeedbackForm] = this; this.$form = $(formEl); this.$form.submit(this.sendStuff); this.alerts = $('#something'); } sendStuff(e) { e.preventDefault() if (this[myFeedbackForm].alerts.length) { window.alert('Notice... stuff') } } } new FeedbackForm(document.forms[0]).$form.submit();实例相关联。

答案 1 :(得分:1)

您可以使用arrow function

  

与函数表达式相比,箭头函数表达式(也称为胖箭头函数)具有更短的语法,并且词汇绑定此值

这应该这样做:

this.$form.submit(e => this.sendStuff(e));

答案 2 :(得分:0)

尝试从主要内部的两个函数范围之外初始化第二种存储变量:

var that;
class FeedbackForm {

  constructor(formEl) {
    this.$form = $(formEl)
    this.alerts = $('#something');
    that = this;

    this.$form.submit(this.sendStuff)    
  }

  /**
   * Sends the feedback
   * @param {Event} e
   */
  sendStuff(e) {
    e.preventDefault()

    if (that.alerts.length) {
      window.alert('Notice... stuff')
    }

    $.ajax({
      type: that.$form.prop('method'),
      url: that.$form.prop('action'),
      data: that.$form.serialize()
    }).done(() => window.location.reload(true))
  }
}