OO JS Issue

Twinkie

Banned
Messages
1,389
Reaction score
12
Points
0
I am experimenting with object oriented javascript, and I ran into a simple problem. Within a method of an object called by an event, this does not reffer to the object but rather to the caller (in this case, an HTMLLIElement). How can I call another method within a method called by on onclick event?

Problem exemplified here. When I click on the open button, it can't call this.load() because this is referring to the li elements clicked. Any workarounds?
 

essellar

Community Advocate
Community Support
Messages
3,295
Reaction score
227
Points
63
"this" in JavaScript refers to the execution context, so the only time it will consistently refer to the object is when the object is constructed. You can assign the function to a variable during construction rather than merely inlining the function:

function myObject() {
this.load = function (param) {doSomething(param); doSomethingElse();};
}

Forget everything you may know about OOP from Java, C++, C# and so on. JavaScript is very different, even if the syntax looks similar. I'd suggest looking at these sites before going too much further: Douglas Crockford on JavaScript and Eloquent JavaScript.
 

Twinkie

Banned
Messages
1,389
Reaction score
12
Points
0
Thank you for the links, but I have read an OO JavaScript tutorial and feel that I have a firm grasp on the concepts involved. I also understand why my example page is not working, but I do not know a solution. Is there any workarounds to reference the current object when the executive context is the not the object reference?

I have an idea of making the event handler reference a function which uses the object reference to access the method, but that will get very repetitive.
 
Last edited:

Twinkie

Banned
Messages
1,389
Reaction score
12
Points
0
Actually, I found the solution. Using 'function() {list.save()}' works. If there is a better solution, I am all ears.

Thanks for the tut, I see it goes into a lot more depth than the other ones I have seen. w3schools.com in particular is looking worse and worse every day.
 

essellar

Community Advocate
Community Support
Messages
3,295
Reaction score
227
Points
63
There was a time when I "knew" JavaScript (been using it since NSN 2 and had ECMA-262 memorized) and I "knew" OOP (I did it for a living) and couldn't glue them together. JavaScript's syntax put my mind into a particular mode of thinking, and it was difficult to break out of it, even as I began to learn that it is a lot closer to Lisp in character than it is to, say, Java. I needed both of those sites to bend my mind enough to make a bit of progress. Of course, now that my mind is truly bent, I'm not fit company for man nor beast, but...
 

misson

Community Paragon
Community Support
Messages
2,572
Reaction score
72
Points
48
Actually, I found the solution. Using 'function() {list.save()}' works. If there is a better solution, I am all ears.
That's pretty much it, though there are different forms. You need a closure to bind the object to the method. More generally, you can write a function to create this binding:

Code:
function bind(self, meth) {
    if (typeof meth == 'string') {
        meth = self[meth];
    }
    return function () {
        return meth.apply(self, arguments);
    }
}

...
$('open').addEventListener('click', bind(load, load.open), false);
$('save').addEventListener('click', bind(load, 'save'), false);
You just have to be careful you don't introduce a memory leak.

Thanks for the tut, I see it goes into a lot more depth than the other ones I have seen.
You might also want to take a look at Jibbering's Javascript Closures article. It covers this very specific but broadly useful topic.

w3schools.com in particular is looking worse and worse every day.
True dat.
 
Last edited:

Twinkie

Banned
Messages
1,389
Reaction score
12
Points
0
That's pretty much it, though there are different forms. You need a closure to bind the object to the method. More generally, you can write a function to create this binding:

Code:
function bind(self, meth) {
    if (typeof meth == 'string') {
        meth = self[meth];
    }
    return function () {
        return meth.apply(self, arguments);
    }
}

...
$('open').addEventListener('click', bind(load, load.open), false);
$('save').addEventListener('click', bind(load, 'save'), false);
I am sorry, but I don't understand what the parameters for the bind function are on the last two lines? Could you explain?
 

Twinkie

Banned
Messages
1,389
Reaction score
12
Points
0
There was a time when I "knew" JavaScript (been using it since NSN 2 and had ECMA-262 memorized) and I "knew" OOP (I did it for a living) and couldn't glue them together. JavaScript's syntax put my mind into a particular mode of thinking, and it was difficult to break out of it, even as I began to learn that it is a lot closer to Lisp in character than it is to, say, Java. I needed both of those sites to bend my mind enough to make a bit of progress. Of course, now that my mind is truly bent, I'm not fit company for man nor beast, but...
I also learned JavaScript first before moving on to heavier languages like Java, but I found it much easier to accept different programming concepts than you did. Maybe this was because I had the 'benefit' of not learning it all at once, but instead being strung through many different minor tutorials.
 

misson

Community Paragon
Community Support
Messages
2,572
Reaction score
72
Points
48
I am sorry, but I don't understand what the parameters for the bind function are on the last two lines? Could you explain?
The first argument to bind is an object. The second is a function or name of an object property that's a method.

Code:
var thing = {
  foo: function () {
    return this.value ='foo';
  },
  function bar() {
    return this.value = 'bar';
  }
};
function baz() {
    return this.value = 'baz';
}

var thingfoo = bind(thing, 'foo'),
    thingbar = bind(thing, thing.bar);
    thingbaz = bind(thing, baz);
 

essellar

Community Advocate
Community Support
Messages
3,295
Reaction score
227
Points
63
I also learned JavaScript first before moving on to heavier languages like Java, but I found it much easier to accept different programming concepts than you did.

I didn't start with JavaScript. Before I met JS for the first time, I'd worked with FORTRAN, machine language (and assembler) on TI99000s, 6502s and Z80s, several flavours of BASIC and Pascal, Lisp, SmallTalk, C/C++ and APL -- all for a living, and all before the WWW or JavaScript existed. I'd even had a go at a small portable language for embedded systems that had recently been renamed "Java".

JS isn't hard -- it's that the language syntax looks like an ALGOL-derived language like C or Java, but its underlying characteristics are much more like Lisp (or, more specifically, Lingo -- the variety of Lisp that Macromedia used in Director and Authorware -- due to a heavy reliance on runtime environment objects). Gluing JS and OOP together successfully means understanding closures, anonymous functions and prototypes and forgetting about classes and interfaces. Most of the experienced programmers I know had trouble with JavaScript object behaviour until they became able to overlook the superficial similarity to languages they were already coding objects in.
 
Top