JavaScript:创建对此'的引用(例如' var _this = this')vs. bind / call / apply

时间:2014-09-17 17:50:10

标签: javascript closures anti-patterns

在错误的背景下依赖this是一个常见的陷阱。一个人为的例子:

function SomeClass() {
    this.prop = 42;
    document.body.addEventListener('click', function() {
        alert(this.prop); // will be undefined
    });
}
new SomeClass();

解决此问题的一种方法是使用bind(或callapply),例如:

function SomeClass() {
    this.prop = 42;
    document.body.addEventListener('click', (function() {
        alert(this.prop); // works
    }).bind(this));
}
new SomeClass();

另一种选择是通过关闭提供对this的引用,通常是_thisself

function SomeClass() {
    var _this = this;
    this.prop = 42;
    document.body.addEventListener('click', function() {
        alert(_this.prop); // works
    });
}
new SomeClass();

我更喜欢后一种方法,因为我可以声明它一次而不是用bind()包装大量函数,而嵌套回调(我知道它们不是理想的,但在野外看到)变得更简单。但我有一种潜在的怀疑,即a)有这种方法的问题,或者b)我必须这样做或bind首先意味着我做错了。有什么想法吗?

2 个答案:

答案 0 :(得分:3)

您解决此问题的方法"没关系:


function SomeClass() {
    this.prop = 42;
    document.body.addEventListener('click', (function() {
        alert(this.prop); // works
    }).bind(this));
}
new SomeClass();

如果你发现你需要这样做,你真的没有做错任何事情,但根据上下文,如果你担心性能,也许你不想创建新的功能(这就是.bind内部对更改

您可以使用范围变量,而不是进行绑定,而不是第二个示例:


function SomeClass() {
    var _this = this;
    this.prop = 42;
    document.body.addEventListener('click', function() {
        alert(_this.prop); // works
    });
}
new SomeClass();

这里唯一剩下的问题是关于代码可读性,但我的问题是关于品味,这就是我要为这个特殊情况做的事情


function SomeClass() {
    var prop = 42;
    document.body.addEventListener('click', function() {
        alert(prop); // works
    });
}
new SomeClass();

我只是提高了可读性,可能还有一点性能,但我并不认为这是"方式"为了做到这一点,我试图说你应该知道如何使用词法作用域和闭包并使用(或不使用)你认为必须的地方(当然,这取决于背景)

编辑:等等!我分配了this.prop = 42因为我需要公开属性 在这种情况下,我认为设计PoV的最佳实践是通过getter公开它:


function SomeClass() {
    var prop = 42;
    document.body.addEventListener('click', function() {
        alert(prop); // works
    });
    this.getProp = function() {
      return prop;
    };

    this.setProp = function(newValue) { // prop is supposed to be modifiable ?
      prop = newValue;
    };
}
new SomeClass();

关于设计的另一个侧面说明与"这个"问题是,与班级中的全局对象进行交互并不合适,我会这样做:


function SomeClass(receiver) {
    var prop = 42;
    receiver.addEventListener('click', function() {
        alert(prop); // works
    });
}
new SomeClass(document.body);

答案 1 :(得分:2)

  

这种方法有问题吗?

不,没关系。我甚至认为,与bind(及其ES3不支持)相比,问题更少。有时看到的陷阱是忘记var(并且如果不是严格模式则引入全局变量),但如果你理解闭包可能不再是问题。

  

或者我必须这样做或首先绑定的事实意味着我做错了。

不,这就是使用this的调用方法在JavaScript中的工作方式。我并不是说错误的设计不能异常频繁地使用self / bind,但好的设计也包含这种模式。