0

The following code below is javascript obeserver pattern, but when it execute "subject.subscribeObserver(observer1);", error occurs that "can not read property push of undefined", it seems that I can not access subject.observers. Why does this happen? In subscribeObserver function I keep this.observers referrence, but subject instance still not access to it. When I use prototype pattern but not return object pattern it works,that is really puzzle me.

var Subject = function() {
        this.observers = [];

        return {
            subscribeObserver: function(observer) {
                console.log(this);
                this.observers.push(observer);
            },
            unsubscribeObserver: function(observer) {
                var index = this.observers.indexOf(observer);
                if (index > -1) {
                    this.observers.splice(index, 1);
                }
            },
            notifyObserver: function(observer) {
                var index = this.observers.indexOf(observer);
                if (index > -1) {
                    this.observers[index].notify(index);
                }
            },
            notifyAllObservers: function() {
                for (var i = 0; i < this.observers.length; i++) {
                    this.observers[i].notify(i);
                };
            }
        };
    };

    var Observer = function() {
        return {
            notify: function(index) {
                console.log("Observer " + index + " is notified!");
            }
        }
    }

    var subject = new Subject();

    var observer1 = new Observer();
    var observer2 = new Observer();
    var observer3 = new Observer();
    var observer4 = new Observer();

    subject.subscribeObserver(observer1);
Jerry
  • 91
  • 1
  • 1
  • 7

1 Answers1

0

When I […] not return object […] it works, that is really puzzle me.

Well yes, you are returning a new object from your constructor. Which means the this object (that you stored the .observers property on) is completely forgotten about. In the subject.subscribeObserver() call, the this in the method refers to subject, i.e. the returned object. You should be able to see that from the console.log(this) - the logged object is the one with the methods, but no array.

You could put the array on the returned object:

function Subject() {
    return {
        observers: [],
        subscribeObserver(observer) {
            …
        },
        …
    };
}

but I would recommend to just use the prototype pattern with all its benefits.

Bergi
  • 630,263
  • 148
  • 957
  • 1,375