OO JavaScript - 避免自我 = 这个

OO JavaScript - Avoiding self = this

本文关键字:自我 这个 JavaScript OO      更新时间:2024-02-15

有谁知道在以 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);
    }
};

在你的第一个函数中,你可以做到这一点...

$.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);

不,如果您想在不同的上下文(例如回调(中引用this,则需要这样做,否则它将被重新分配给另一个对象,例如 window .

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

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

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

对于非 ES5 浏览器,您可以使用填充程序,例如此处的垫片:https://github.com/kriskowal/es5-shim

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

一些JavaScript框架有自己的事件处理机制,允许你为处理程序函数设置上下文。这样,您可以简单地将this指定为上下文,而不是使用 self = 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();
}

您始终可以将方法绑定到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);
    }
};

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

我在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();