views:

38

answers:

2

The following code doesn't work as I intuitively expect it to:

function MyObject(input) {
   input.change(this._foo);
   this.X = undefined;
}

MyObject.prototype._foo = function() {
   alert("This code is never called");
   // but if it did
   this.X = true;
}

var test_input = $("input#xyz"); // a random, existing input

var m = MyObject(test_input); // attach handler (or try to)

test_input.change(); // trigger event

alert(m.X); // undefined

I'd expect that _foo() would be called (and, if that ever happens, that the this variable in _foo() would be an instantiation of MyObject.

Does anyone know why this doesn't work, and of any alternative pattern for passing an object to an event handler?

Thank you for reading.

Brian

+2  A: 

To create an object in Javascript, use new.

var m = new MyObject(test_input); // attach handler (or try to)
KennyTM
@KennyTM - I've been trying to avoid `new`, as Douglas Crockford suggests, but you're correct in pointing out at least this one fault with the code. :)
Brian M. Hunt
@Brian: Without using `new`, `this` inside `MyObject` points to `window`, rather than the "instance" of `MyObject`. I put "instance" within quotes, as by not wanting to use `new`, you're never going to create instances of anything.
Matt
+2  A: 

As Kenny points out you're missing the new. You also need to make sure that this in _foo refers to the MyObject instance
One way to do it:-

function MyObject( input ) {
    var _this = this;
    input.change( function() {
       // explicitly set the `this` in _foo to `_this`
        _this._foo.call( _this );
    });
   this.X = undefined;
}

MyObject.prototype._foo = function( event ) {
   alert("This is called");
   // and 'this', being 'm', has X set to true
   this.X = true;
   // the textbox must be accessed by 'event.target' not 'this' if you need it
}

var test_input = jQuery("input#xyz"); // a random, existing input

var m = new MyObject(test_input); // attach handler (or try to)

test_input.change(); // trigger event

alert(m.X); // true

P.S You can't avoid using the new operator by leaving it out! :)

meouw