使用 Function.prototype.bind 或保存的引用

Using Function.prototype.bind or saved reference

本文关键字:保存 引用 bind Function prototype 使用      更新时间:2023-09-26
这是

主观的(基于意见的) - 但只是在一定程度上,不要急于投票关闭。在工作中引起一些争论,因为每个人都有不同的意见,人们正试图强制执行一种单一的方式。

简单的上下文:当您可以选择在闭包中保存对实例的引用或使用填充Function.prototype.bind时,您认为这两种方法都有哪些可能的缺点?

为了说明可能的用例,我只是编造了一些类方法。

模式一,保存的参考:

obj.prototype.addEvents = function(){
    var self = this;
    // reference can be local also - for unbinding. 
    this.onElementClick = function(){
        self.emit('clicked');
        self.element.off('click', self.onElementClick);
    };
    this.element.on('click', this.onElementClick);
};

模式二,一个简单的fn.bind:

obj.prototype.addEvents = function(){
    // saved reference needs to be bound to this to be unbound
    // once again, this can be a local var also.  
    this.onElementClick = function(){
        this.emit('clicked');
        this.element.off('click', this.onElementClick);
    }.bind(this);
    this.element.on('click', this.onElementClick);
};

模式二半,事件原型方法:

obj.prototype.addEvents = function(){
    // delegate event to a class method elsewhere 
    this.element.on('click', this.onElementClick.bind(this));
};
obj.prototype.onElementClick = function(){
    this.emit('clicked');
    this.element.off('click', this.onElementClick); // not matching due to memoized bound 
};

就我个人而言,我认为没有一种正确的方法可以做到这一点,应该根据具体情况进行判断。我非常喜欢尽可能保存的参考模式。我被告知了。

问题回顾:

是否有任何GC问题需要考虑/注意?

在这两种方法上,您是否能想到任何其他明显的缺点或陷阱?

Polyfill 性能或事件原生.bind与保存的引用?

我个人的偏好是使用保存的参考方法。关于this价值的推理有时可能非常困难,因为 JavaScript 对待this的方式。

绑定很好,但如果你错过了.bind(this)它看起来像一个错误。

后者暴露了太多;每次你需要回调时,你都需要在API中公开另一个帮助程序。


有很多方法可以使用原型。我认为最重要的是选择一个并坚持下去。

是否有任何GC问题需要考虑/注意?

较旧的引擎不会从闭包中推断出仍在使用的变量,而是保留整个范围。使用 bind 确实很容易,因为上下文是显式传递的,并且未收集的范围不包含其他变量。

但是,如果您无论如何都使用函数表达式(如模式 #1 和 #2),这并没有区别。

在这两种方法上,您是否能想到任何其他明显的缺点或陷阱?

保存参考:

    需要一个
  • 额外的行来声明变量,有时甚至需要一个全新的作用域(IEFE)
  • 代码无法轻松移动,因为您需要重命名变量

使用绑定:

  • 在函数表达式的末尾很容易被忽略(就像 IEFE 的调用一样),从上到下读取时不清楚this指的是什么
  • 容易忘记

我个人倾向于使用 bind ,因为它简洁,但只使用在其他地方声明的函数(方法)。

Polyfill 性能或事件本机 .bind 与保存的引用?

你不在乎。


在您的示例中,您实际上不需要对绑定函数和 off 方法的引用。 jQuery 可以自己处理这个问题,您可以使用 one 方法来绑定一次触发侦听器。然后你的代码可以缩短为

obj.prototype.addEvents = function(){
    this.element.one('click', this.emit.bind(this, 'clicked'));
};