只为构造函数的所有实例触发一次事件侦听器

Firing eventListener only once for all the instances of my constructor?

本文关键字:一次 侦听器 事件 构造函数 实例      更新时间:2023-09-26

我在构造函数的所有实例中都有一个共享属性:

function Me() { }
Me.prototype.window = {};
我想在调整

大小时更新它的内容window但我想为每个调整大小事件只做一次,无论我的构造函数创建了多少个实例。

从逻辑上讲,如果我定义 eventListener 如下,在我的实例初始化中,它将被多次触发

function Me() {
  window.addEventListener('resize', function() {
    this.window = window.outerWidth;
  }.bind(this));
}
var a = new Me();
var b = new Me();
// on resize, the callback is called twice

我该怎么做?

我该怎么做?

具有指示是否绑定事件处理程序的标志。然后,在构造函数中,您只需要检查标志:

if (bindHandler) {
  // ... bind handler
  bindHandler = false;
}

如何/在哪里存储标志取决于您。

以为我会放回我给出的所有答案,以显示 OP 如何没有预先提供所有相关信息。此外,他最终想出并标记为正确的答案是我提供的答案,他击落了。


首先,我提供了可能是最简单的解决方案:

将以下内容完全放在构造函数之外。调整窗口大小时,将更新所有实例的共享属性 - - 。

window.addEventListener('resize', function() {
  Me.prototype.window = window.outerWidth;
};

然后,OP 添加了新信息,说明这不好,因为如果不存在Me实例,回调仍将在原型上注册。


然后我提供了这个,有趣的是,当其他人发布它时,他将其标记为答案。

下一个解决方案必须是在注册事件侦听器之前跟踪是否存在任何Me实例。这意味着您需要跟踪是否存在任何实例:

// Global variabel to track if Me instances exist
var meInstances = false
var me1 = new Me();
meInstances = true;
if(meInstances){
   window.addEventListener('resize', function() {
     Me.prototype.window = window.outerWidth;
   };
}

但是,当我发布它时,回应是:"你完全让所有的类、构造函数和类似的东西变得无用。没有隔离,你白白添加了很多代码,而且解决方案并不强大。事实上,OP 随后提出了自己的解决方案,该解决方案使用数组来存储实例,然后可以检查数组的长度以查看是否有任何实例。我实际上打算建议这样做,但选择了布尔标志,因为 OP 一直说他想要简单。


所以,我提供了这个:

怎么样:

function Me() {
  // This code only runs when instance is being made
  // This instance is registers a callback
  window.addEventListener('resize', function() {
    // Callback modifies single Prototype that all instances share
    Me.prototype.window = window.outerWidth;
  });
}
Me.prototype.window = {};

现在,我不完全认可这是一个好的解决方案,但从 OP 在每个建议后不断添加的所有约束来看,这似乎是最后的手段。但是,再次被拒绝。

在这里添加我在最终代码中使用的解决方案。
我为完整性添加了一个destroy方法:

function Me() {
  this.init();
}
Me.prototype.window = 0;
// function used to update this.window
Me.prototype.onResizeBound = null;
Me.prototype.onResize = function() {
  Me.prototype.window = window.outerWidth;
};
// if there are no instances of Me, initialize the event listener
// then, add this instance to the instances list
Me.prototype.init = function() {
  if (this.instances === 0) {
    Me.prototype.onResizeBound = this.onResize.bind(this);
    window.addEventListener('resize', Me.prototype.onResizeBound);
  }
  this.instances++;
};
// remove this instance to the instances list
// if there are no more instances in the list, remove the event listener
Me.prototype.destroy = function() {
  this.instances--;
  if (this.instances === 0) {
    window.removeEventListener('resize', Me.prototype.onResizeBound);
  }
};
Me.prototype.instances = 0;

例:

var a = new Me(); // added event listener
var b = new Me(); // not added event listener since one is already set
b.destroy(); // not removed event listener since one instance is still there
a.destroy(); // removed event listener since there are not other instances