0

I am trying to figure out JavaScript OOP, I tried the following which works but fails when I need to make a change to a class variable on a specific instance.

I have "myname" with a default value, I then change it for a specific instance and in an event handler I print it's value. I get the default value and not the updated one.

how can I change the code to support this ?

thanks

function myClass () {}

myClass.prototype = 
{

    myname : "test",

    test  : function (filename)
    {
        var img = createSomething ();
        img.container = this;

        img.addEventListener('click', this.onClick);                    
    }, 


    onClick : function (e)
    {
        trace ("click: " + e.source.container.myname); // this will print "test" and not "dave"
    }

};



var instance = new myClass ();

instance.myname = "dave";

instance.test();

3 Answers 3

2

I don't know what trace() and e.source are, but when I take your example, and use console.log() and e.target.container.myname, it works perfectly.

Example: http://jsfiddle.net/L2UMC/2/

(note that the example is only intended to work in browsers that support addEventListener)

function myClass() {}

myClass.prototype = {

    myname: "test",

    test: function(filename) {
        var img = new Image();
        img.src = "http://dummyimage.com/120x90/f00/fff.png&text=my+image"
        img.container = this;

        img.addEventListener('click', this.onClick, false);
        document.body.appendChild(img);
    },
    onClick: function(e) {
        console.log("click: " + e.target.container.myname); 
    }
};
var instance = new myClass();
instance.myname = "dave";
instance.test();

EDIT: Made the addEventListener more compatible by adding the 3rd argument, as correctly suggested by @Felix Kling.

Sign up to request clarification or add additional context in comments.

2 Comments

I guess you more less copied&pasted the original code, but note that at least Firefox needs three arguments for addEventListener: img.addEventListener('click', this.onClick, false);(it will throw an error otherwise). This makes it at least a bit more compatible ;)
@Felix: Thanks for the info. I only tested in Chrome. I'll update. Main point was that the inheritance was working properly. This is most certainly limited in terms of browser compatibility.
0

If you really want to do OOP, you must use a bind function. It is extremely useful when you want to attach event handlers that are bound to your object rather than the global object.

function bind(func, context) {
     return function() {
          return func.apply(context, Array.prototype.slice.call(arguments));
     }
}

Then you do this-

function MyClass() {}

MyClass.prototype = {

    myname: "test",

    test: function(filename) {
        var img = new Image();
        img.src = "http://dummyimage.com/120x90/f00/fff.png&text=my+image"

        img.addEventListener('click', bind(this.onClick, this), false);
        document.body.appendChild(img);
    },
    onClick: function(e) {
        //this here refers to the instance of MyClass
        console.log("click: " + this.myname); 
    }
};
var instance = new MyClass();
instance.myname = "dave";
instance.test();

PS: As a convention, constructor functions (or 'Classes') begin with an uppercase letter.

Comments

0

Note: not a direct answer to the question.

For OOP in Javascript I would strongly recommend using following Class class by John Resig himself: http://ejohn.org/blog/simple-javascript-inheritance/

It makes inheritance so much nicer...

Comments

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.