2

I apologise for such a simple question - I'm new to JS, though I thought I understand this pattern (combination constructor/prototype).

In my code (snippet below), my prototype methods for my "Journal" type cannot read instance properties of objects of journal type. But my other types work fine, and I can't see the difference between my journal type and my other types.

Clicking on my save button (invoking updateEntry method, code below) gives me this error:

Uncaught TypeError: Cannot read property 'length' of undefined 

Here is the relevant JavaScript -

var Journal = function(saveBtn) {
    this.entries = [];

    this.saveBtn = document.getElementById(saveBtn);
    this.saveBtn.onclick = this.updateEntry;
};

Journal.prototype.updateEntry = function() {
    console.log('Let\'s see if entries accessible: ' + this.entries.length);
};

var journal = new Journal('btn');

Why can journal's invocation of Journal.prototype.updateEntry() not view journal.entries?

James Peterson
  • 586
  • 4
  • 9

1 Answers1

2

It is being called with the DOM element saveBtn as this, instead of the Journal object.

Do this instead:

this.saveBtn.onclick = this.updateEntry.bind(this);

or if using IE8 or below,

var self = this;
this.saveBtn.onclick = function() { self.updateEntry(); };

Explanation:

When the click happens, the follow is being called:

saveBtn.onclick();

Thus saveBtn is the this in the function. bind (or the self variable) make sure that the this in the context of Journal is retained, no matter on what object the function is being called.

Paul Draper
  • 78,542
  • 46
  • 206
  • 285
  • 1
    @jpau: `addEventListener` should exhibit the same problem. It doesn't matter which method you use to bind the event handler. If the function isn't bound, `this` will always refer to the DOM element the handler is assigned to. – Felix Kling Jan 22 '14 at 06:40
  • 1
    You're correct. Thanks Felix. Thanks Paul. – James Peterson Jan 22 '14 at 06:44