OO JavaScript - 避免自我=这个

时间:2012-07-25 01:34:55

标签: javascript

当以OO方式使用JavaScript时,是否有人知道如何绕过声明var self = this?我经常看到它并且好奇它是否只是你必须要做的事情,或者是否真的有办法(也许是一个类库?)让你绕过它?我确实知道为什么有必要(这有功能范围)。但你永远不知道那里有什么聪明的方法......

例如,我通常在JS中编写这样的“类”:

function MyClass() {

}

MyClass.prototype = {

    firstFunction: function() {

        var self = this;

        $.ajax({
            ...
            success: function() {
                self.someFunctionCall();

            }
        });
    },

    secondFunction: function() {

        var self = this;

        window.setTimeout(function() {
            self.someOtherFunction();
        }, 1000);
    }

};

6 个答案:

答案 0 :(得分:6)

在你的第一个功能中,你可以这样做......

$.ajax({
    context: this,
    success: function() {
        this.someFunctionCall();

    }
});

在第二个问题中,您可以执行此操作,但您需要在旧版浏览器中使用.bind() ...

window.setTimeout(function() {
    this.someOtherFunction();
}.bind(this), 1000);

使用jQuery,你也可以这样做......

window.setTimeout($.proxy(function() {
    this.someOtherFunction();
}, this), 1000);

答案 1 :(得分:1)

不,如果要在不同的上下文(例如回调)中引用this,则需要执行此操作,否则将重新分配给另一个对象,例如window

顺便说一句,self是一个python约定 - 在JavaScript中人们通常使用约定that = this。但这只是个人品味的问题。

答案 2 :(得分:1)

ES5添加了名为bind的标准方法,它允许您绑定函数的this以及前n个参数。在上面的示例中,您可以通过调用self来避免使用bind

$.ajax({ 
    ... 
    success: function() { 
        this.someFunctionCall(); 
    }.bind(this); 
}); 

对于非ES5浏览器,您可以使用垫片,例如:https://github.com/kriskowal/es5-shim

作为助手,我会避免在编码模式中使用self,因为self被定义为全局变量,它等于全局范围window。换句话说,如果您不小心忘记定义self,您将默默地将全局范围作为值而不是异常。如果您改为使用that,则会收到异常(除非您上面的人定义了异常)。

答案 3 :(得分:0)

一些javascript框架有自己的事件处理机制,允许您为处理函数设置上下文。这样,您只需将self = this指定为上下文,而不是使用this

我想到的其他可能性是在全局范围内的某个地方传递上下文。像

function MyClass() {
    MyClass.instances.push(this);
}

MyClass.instances = new Array();
MyClass.getInstanceBySomeRelevantParameter = function(param) {
     for (var i = 0; i < MyClass.instances.length; i++)
         if (condition(param))
             return MyClass.instances[i];
}

...

success: function(event) {
    MyClass.getInstanceBySomeRelevantParameter(event).someFunctionCall();
}

答案 4 :(得分:0)

您可以随时将方法绑定到this,然后按如下方式使用它:

function MyClass() {

}

MyClass.prototype = {

    firstFunction: function() {

        var funct = someFunctionCall.bind(this);

        $.ajax({
            ...
            success: function() {
                funct();

            }
        });
    },

    secondFunction: function() {

        var funct = someOtherFunction.bind(this);

        window.setTimeout(function() {
            funct();
        }, 1000);
    }

};

对于属性,只需将它们分配给另一个变量。

答案 5 :(得分:0)

我骗了JSFiddle,想出了下面的内容。它确实假设您使用的是顶级命名空间。这使得你只需要声明self一次(在底部)。我将这个类包装在一个匿名函数中,所以self不会有全局范围。小提琴是:http://jsfiddle.net/bdicasa/yu4vs/

var App = {};
(function() {
    App.MyClass = function() { }

    App.MyClass.prototype = {

        firstFunction: function() {

            console.log('in first function');
            console.log(self === this); // true
        },

        secondFunction: function() {


            window.setTimeout(function() {
                self.firstFunction();
                console.log(self === this); // false
            }, 100);
        }

    };
    var self = App.MyClass.prototype;
})();

var myClass = new App.MyClass();
myClass.secondFunction();