传递对象的成员函数时绑定"this"

ach*_*how 3 javascript singleton closures

我定义了一个"类",并且只创建了一个实例.该实例拥有一个最终被传递的成员函数(它是一个鼠标处理程序,但这并不重要).因为我只会创建一个"类"的实例,所以我决定使用对象文字将其重写为单例.

所以我有

var mySingleton = {
    theObjects : [];
}

mySingleton.mouseHandler = (function() {
    var that = this;
    return function (e) {
        for (var indx = 0; indx < that.theObjects.length; indx++) {
            // do something to that.theObjects[indx];
        }
    }
}());

mySingleton.addObject = function(newObj) {
    this.theObjects.push(newObj);
}
Run Code Online (Sandbox Code Playgroud)

但是,当我尝试使用此代码时(添加几个对象之后),我不断得到一个.theObjects是未定义的错误.它指的是for循环中的行.

gil*_*ly3 7

2015年更新 - Function.bind()用于指定this函数内的值.然后,that您可以使用,而不是使用this.

mySingleton.mouseHandler = function (e) {
    for (var indx = 0; indx < this.theObjects.length; indx++) {
        // do something to this.theObjects[indx];
    }
}.bind(mySingleton);
Run Code Online (Sandbox Code Playgroud)

如果你想mouseHandler拥有'moused'元素的上下文,这不起作用.为此,请使用下面的原始答案.

如果您需要先支持IE8或(天堂禁止),您需要使用polyfill.


由于您正在调用mouseHandler立即创建的函数,因此它在上下文中运行window,而不是mySingleton.所以that指的是window.不要立即调用它,只需将其更改为方法,以便它在以下语境中运行mySingleton:

mySingleton.getMouseHandler = function() {
    var that = this;
    return function() { ... };
};
myElement.onclick = mySingleton.getMouseHandler();
Run Code Online (Sandbox Code Playgroud)

当然,既然你已经在使用单例,你可以直接引用它.在您的点击处理程序中,检查that.theObjects,而不是检查mySingleton.theObjects.或者,mouseHandler改变var that = this为var that = mySingleton.

编辑:或者,在调用它时将上下文传递给您的匿名函数:

mySingleton.mouseHandler = (function() {
    var that = this;
    return function (e) {
        for (var indx = 0; indx < that.theObjects.length; indx++) {
            // do something to that.theObjects[indx];
        }
    }
}).call(mySingleton);
Run Code Online (Sandbox Code Playgroud)