首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >从类绑定函数时保存“此”

从类绑定函数时保存“此”
EN

Stack Overflow用户
提问于 2016-06-29 17:04:55
回答 3查看 312关注 0票数 3

我在JavaScript中有一个简单的类:

代码语言:javascript
运行
复制
function MyCounter() {
  this.counter = 0;
  $('#button').click(this.run);
}

MyCounter.prototype.run = function() {
  this.counter += 1;
  return console.log(this.counter);
};

调用该类的方式如下:

代码语言:javascript
运行
复制
var myCounter = new MyCounter();

HTML包含一个带有ID=“按钮”的可点击按钮。单击此按钮将在myCounter实例中增加一个内部变量。显然,它失败是因为this.counter不存在,因为在执行绑定处理程序this时,它等于事件,而不是myCounter实例。

解决这一问题的一个简单方法是将“此”保存到其他变量中,并将调用实际处理程序包装为一个匿名函数:

代码语言:javascript
运行
复制
function MyCounter() {
  this.counter = 0;
  var this2 = this;
  $('#button').click(function() {
    this2.run();
  });
}

有没有更好更干净的方法?或者至少,对于如何命名这样的“临时的这个”变量,可能有一个通用的协议/风格指南?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2016-06-29 17:06:24

您可以只使用.bind()

代码语言:javascript
运行
复制
$('#button').click(this.run.bind(this));

.bind()创建了一个小型存根函数,它实际上是为您实现的:

代码语言:javascript
运行
复制
var self = this;
$('#button').click(function() {
    return self.run();
});
票数 2
EN

Stack Overflow用户

发布于 2016-06-30 02:16:09

在javascript中,这并不是真正的粗糙。这样做的一个常见方法是:

代码语言:javascript
运行
复制
function MyCounter() {
  this.counter = 0;

  var self = this;
  this.run = function() {
    self.counter += 1;
    console.log(self.counter);
  };

  $('#button').click(this.run);
}

使用es6语法,一个常见的模式是绑定构造函数中的函数:

代码语言:javascript
运行
复制
class MyCounter {
  constructor() {
    this.counter = 0;
    this.run = this.run.bind(this);

    $('#button').on('click', this.run);
  }

  run() {
    this.counter += 1;
    console.log(this.counter);
  }

  // And now you can also remove the event listener:
  destroy() {
    $('#button').off('click', this.run);
  }
}

但是,这种模式也可以应用于创建js类的旧方法:

代码语言:javascript
运行
复制
function MyCounter() {
  this.counter = 0;
  this.run = this.run.bind(this);

  $('#button').on('click', this.run);
}

MyCounter.prototype.run = function() {
  this.counter += 1;
  console.log(this.counter);
}

// And again you can also remove the event listener:
MyCounter.prototype.destroy = function() {
  $('#button').off('click', this.run);
}

这很好,因为在启动类之前,您现在可以从prototype访问run方法。

但我认为这里的底线是,在创建类实例之前,不能将其绑定到类实例。

侧注:在我的所有示例中,run方法在启动时都绑定到类实例。这意味着run方法不需要再次绑定,即$('#button').click(this.run.bind(this));

还有另一种模式(带有私有变量的单例):

代码语言:javascript
运行
复制
var myCounter = (function() {
  var counter = 0

  function run() {
    counter += 1
    console.log(counter)
  }

  $('#button').on('click', run)

  return {
    run: run,
    destroy: function() {
      $('#button').off('click', run)
    }
  }
})()

因为只有一个#button实例,所以没有理由选择多个类实例。

票数 1
EN

Stack Overflow用户

发布于 2016-06-30 02:28:06

我不知道它是什么,但我只是不喜欢bind函数。作为另一种选择,您可以通过将对象实例封装在匿名函数中,从而将this绑定到对象实例,然后使用HTML5的onclick属性将函数绑定到模板。

柱塞演示

代码语言:javascript
运行
复制
var MyCounter = (function () {
    function MyCounter(counter) {
        this.counter = counter || 0;
    }
    MyCounter.prototype.run = function () {
        return alert(this.counter += 1);
    };
    return MyCounter;
}());


var counterInstance = new MyCounter(10);
window.counterInstance = counterInstance;

...

<button onclick="counterInstance.run()">Test</button>

另一种策略--一种更面向对象的方法--将元素引用传递给类本身,并在类构造函数中分配方法。看起来应该是:

代码语言:javascript
运行
复制
class Counter {

    constructor(elementRef, counter = 0) {
        this.element = elementRef;
        this.counter = counter;

        //native HTML type
        this.element.onclick = () => this.run();

       //alternatively
       this.element.addEventListener('click', this.run);
    }

    function run() => { return this.counter++; }

}
票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/38105978

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档