3

I've got a big Javascript project that I'm trying to refactor into pseudo-classes:

jsFiddle: http://jsfiddle.net/waitinforatrain/7T42w/

var MyNameSpace = {}

MyNameSpace.MyClass = function() {
    this.doSomething = function () {
        return "hello";
    }

    this.doSomething2 = function() {
        var x = this.doSomething() + " world";
        alert(x);
    }

    this.doSomething2(); //Works fine

    $("#mydiv").click ( this.doSomething2 ); //Doesn't work
}

var class = new MyNameSpace.MyClass();

The reason the click event causes an error is that this refers to the #mydiv element.

How am I supposed to design the above so that I can access the element that was clicked but can also call doSomething()?

3
  • @Javier JavaScript does not have classes. So it's a pseudo class. Commented Apr 20, 2011 at 21:02
  • OO, classes and other things are design concepts, not language features Commented Apr 20, 2011 at 21:44
  • Sure they're language features, some languages support different types of inheritence etc. Commented Apr 20, 2011 at 21:53

3 Answers 3

6

You need to cache the context reference and wrap the call in a closure:

var MyNameSpace = {}

MyNameSpace.MyClass = function() {
    var context = this;

    context.doSomething = function () {
        return "hello";
    }

    context.doSomething2 = function() {
        var x = context.doSomething() + " world";
        alert(x);
    }

    // You can do this:
    context.doSomething2();

    // Or this:
    $("#mydiv").click(function(e) {
        context.doSomething2();
    });
}
Sign up to request clarification or add additional context in comments.

2 Comments

So obvious now :) Just for the record there's no need to wrap the call in a function, if you pass context.doSomething2 (without brackets) it does the same thing
I agree, but I like to keep my click event arguments separate from my instance method arguments.
2
this.doSomething2 = $.proxy(function() {
    var x = this.doSomething() + " world";
    alert(x);
}, this);

$.proxy binds the this scope to the context variable inside said function.

Comments

0

Save a reference to this in the outer scope:

MyNameSpace.MyClass = function() {

    var that = this;

    this.doSomething = function () {
        return "hello";
    }

    this.doSomething2 = function() {
        var x = that.doSomething() + " world";
        alert(x);
    }

    this.doSomething2(); //Works fine

    $("#mydiv").click ( this.doSomething2 ); //Doesn't work
}

The function assigned to doSomething2 is said to "close over" the variables in its lexical scope and so has access to their values even once MyClass has returned. This allows us to access the doSomething method through the reference to the instance we assigned to that.

2 Comments

Yeah, this would work. The only thing I would recommend is that since you are already caching the context, why not use it everywhere instead of one place. Just my 2 cents...
@Eli personally I don't like using the cached context everywhere. I prefer to only use that where I can't use this. Better yet bind the method to this.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.