我有一个类Gadget,其中一个方法consider定义为:

function Gadget() {

    this.consider = function (arg) {
        alert(arg);
    };

    if ("WebSocket" in window) {
        var ws = new WebSocket(...);
        // the rest truncated

        ws.onmessage = function (evt) {
            consider(evt.data);
        };
    }
}


但是,由于consider失败,我无法使TypeError工作。

Uncaught TypeError: Object #<Gadget> has no method 'consider'


如果我改用this.consider,则TypeError与WebSocket对象一起出现。如果我尝试parent.consider,则Object对象会给我同样的错误。

现在,我的解决方法是使用已声明实例的方法,如下所示:

var player = new Gadget();


并使用player.consider(evt.data)代替。我不喜欢这样做,但是可以。如何重新排列代码,使其不依赖于对象的已定义实例?

最佳答案

您可以通过两种方式克服这一问题。

1)使用私人功能

function Gadget() {

    function consider(arg){
        alert(arg);
    }

    this.consider = consider;

    if ("WebSocket" in window) {
        var ws = new WebSocket(...);
        // the rest truncated

        ws.onmessage = function (evt) {
            consider(evt.data);
        };
    }
}


这样,您在consider()类中就有了一个私有的Gadget函数,即使该类的实例调整了自己的consider方法(例如var x=new Gadget(); x.consider=...),Web套接字仍将按预期工作;

2)“缓存” this

function Gadget() {
    this.consider = function(arg){
        alert(arg);
    };

    if ("WebSocket" in window) {
        var ws = new WebSocket(...);
        // the rest truncated

        var self=this;
        ws.onmessage = function (evt) {
            self.consider(evt.data);
        };
    }
}


这样,您的网络套接字事件将始终使用Gadget希望consider成为实例的任何实例。

Here is a jsfiddle demo演示了这两种方式。注意,我故意调整了consider实例的Gadget2方法(第二个按钮)。单击这些按钮以查看其他按钮。

07-24 15:50