`var self = this`被认为是代码味?

时间:2016-03-24 13:31:59

标签: javascript

目前在复数视频上观看“高级Javascript”。在课程的“面向对象”部分,Kyle让我完全失去了一个部分:

NotesManager.prototype.showHelp = function() {
    this.$help.show();

    document.addEventListener("click",function() __handler__(evt) {
        evt.preventDefault();
        evt.stopPropagation();
        evt.stopImmediatePropagation();

        document.removeEventListener("click", __handler__,true);
        this.hideHelp();
    },true);
};

this引用现在将成为导致this.hideHelp();无效的按钮。他首先尝试使用硬绑定解决方案来解决问题:

NotesManager.prototype.showHelp = function() {
    this.$help.show();

    document.addEventListener("click",function() __handler__(evt) {
        evt.preventDefault();
        evt.stopPropagation();
        evt.stopImmediatePropagation();

        document.removeEventListener("click", __handler__,true);
        this.hideHelp();
    }.bind(this),true);
};

他所说的解决了this问题但导致了另一个问题。上面使用了一个命名函数,因此它可以解除绑定。但是他说这个函数的名称不是现在绑定的。绑定的函数是新的硬绑定函数,因此它不能解除绑定,因为我们没有对硬绑定函数的引用。咦?谁能解释一下。他没有详细说明。

之后,他解释了解决问题的最佳方法是使用自引用:

NotesManager.prototype.showHelp = function() {
    var self = this;
    self.$help.show();

    document.addEventListener("click",function() __handler__(evt) {
        evt.preventDefault();
        evt.stopPropagation();
        evt.stopImmediatePropagation();

        document.removeEventListener("click", __handler__,true);
        self.hideHelp();
    },true);
};

通常他说他建议避免这样做,因为它表明代码味道,但他说这是最好的解决方案之一。他继续说你自己在脚下射击,因为你很难实施this机制,然后你又回到了词汇范围。他说,使用自我引用的人通常不了解这些机制是如何工作的。我从来没有听说过自我引用是一种代码味道。我见过它广泛使用。为什么一般表示代码味?也许它应该只在你有一个事件处理程序时使用?

2 个答案:

答案 0 :(得分:1)

这是Javascript中常见的范围问题,新的胖箭头符号应该有所帮助。根据我的经验,每个人都讨厌使用self = this,但无论如何都要这样做 - 主要是因为它保持可读性。

胖箭头符号对此问题有很大帮助,并且使用 self进行介绍会导致成为代码异味

  

在箭头函数之前,每个新函数都定义了自己的this值   (构造函数中的新对象,在严格模式下未定义)   函数调用,如果函数被调用为上下文对象   “对象方法”等)。事实证明这很烦人   面向对象的编程风格。

- MDNCode强调我的。)

答案 1 :(得分:-1)

修改:将lexical范围更改为functional范围 为什么它被认为是代码味道的原因是因为JavaScript中的所有东西都是功能范围的。但是,this是动态范围的。

void foo()
{
    int floo = 1;

    void foo2()
    {
        console.log(floo);
    }
}

每个内在级别都可以访问外层。

但与this相反,它不能做到这一点。

void foo()
{
    //this refers to foo()
    console.log(this)

    void foo2()
    {   //this refers to foo2()
        console.log(this);
    }
}
人们可能会感到困惑,但对我来说这并不是什么大不了的事。