OO javascript... this doesn't appear to point to the object

E

ensemble

I'm trying to utilized a more object-oriented approach to managing
window events in javascript. Thus, I am creating a "controller" object
to handle events and interact with the server. However, I apparently
don't fully understand what "this" refers to. In the code below I was
expecting that when the button was clicked (handleDeleteButtonClicked
function) that "this" would be pointing at a ViewController object.
Instead it was the Button (HtmlInputElement).

Can somebody help me understand?

<html>
<head>
<script>
/* Constructor */
function ViewController() {
this.foo = "bar";
}

/* delete button handler */
ViewController.prototype.handleDeleteButtonClicked = function() {
window.alert("delete clicked, this=" + this + " this.foo= " +
this.foo);
};

/* initializer */
ViewController.prototype.initialize = function() {
document.getElementById("delete-button").onclick =
this.handleDeleteButtonClicked;
};
</script>
</head>
<body onload="javascript:new ViewController().initialize();">
<input id="delete-button" type="button" value="Delete">
</body>
</html>
 
M

Michael Winter

ensemble said:
I'm trying to utilized a more object-oriented approach to managing
window events in javascript. Thus, I am creating a "controller"
object to handle events and interact with the server. However, I
apparently don't fully understand what "this" refers to.

Then search the Google Groups archives for phrases like "the this
operator" and such. It has been discussed many times in the past.

Be careful to ignore anything a poster named "VK" has to say on the matter.

[snip]

Mike
 
V

VK

ensemble said:
I'm trying to utilized a more object-oriented approach to managing
window events in javascript. Thus, I am creating a "controller" object
to handle events and interact with the server.

IMHO your code looks more as an attempt to reproduce other languages
weaknesses and workarounds in javascript. The javascript event model
has enough of its own headaches to add Java's or C++'s ones into it ;-)

<html>
<head>
<title> make KISS - then OOP ! </title>
<meta http-equiv="Content-Type"
content="text/html; charset=iso-8859-1">

<script type="text/javascript">

function EventListener(obj) {

// Lightweight constructor protection:
if (((window) && (this == window))
|| (!obj) || (!obj.tagName)) {
return new Boolean(false);
}

obj.JSInstance = this;

this.foo = 'foo';

for (var i=1; i<arguments.length; i++) {
obj[arguments] = EventListener[arguments];
}
}

EventListener.onmouseover = function() {
this.style.backgroundColor = 'yellow';
}

EventListener.onmouseout = function() {
this.style.backgroundColor = '';
}

EventListener.onclick = function() {
alert(this.JSInstance.foo);
}


function init() {
new EventListener(document.getElementById('btnAdd'),
'onmouseover', 'onmouseout');

new EventListener(document.getElementById('btnEdit'),
'onclick' );

new EventListener(document.getElementById('btnDelete'),
'onmouseover', 'onmouseout', 'onclick' );
}


window.onload = init;
</script>
</head>

<body>
<button id="btnAdd" type="button">Add</button>
<button id="btnEdit" type="button">Edit</button>
<button id="btnDelete" type="button">Delete</button>

</body>
However, I apparently
don't fully understand what "this" refers to.

[this] refers to the *current object* (or by ECMAScript specs it points
to "the object pointed by [this] keyword", which is cool to know but
not very helpful :)

Current object can be:
1) Global object (most of the time)
2) New object instance (in constructor)
3) Object instance owning the called method (more rarely than it should
IMHO)
4) Other object instance transferred by call() or apply() methods
5) Equivalent of *default object* in with (this) {...} construct
6) DOM element received the event in intrinsic method handlers.

By the rules of good show I placed your case at the very end :)
 
E

ensemble

ensemble said:
I'm trying to utilized a more object-oriented approach to managing
window events in javascript. Thus, I am creating a "controller" object
to handle events and interact with the server. However, I apparently
don't fully understand what "this" refers to. In the code below I was
expecting that when the button was clicked (handleDeleteButtonClicked
function) that "this" would be pointing at a ViewController object.
Instead it was the Button (HtmlInputElement).

Can somebody help me understand?

<html>
<head>
<script>
/* Constructor */
function ViewController() {
this.foo = "bar";
}

/* delete button handler */
ViewController.prototype.handleDeleteButtonClicked = function() {
window.alert("delete clicked, this=" + this + " this.foo= " +
this.foo);
};

/* initializer */
ViewController.prototype.initialize = function() {
document.getElementById("delete-button").onclick =
this.handleDeleteButtonClicked;
};
</script>
</head>
<body onload="javascript:new ViewController().initialize();">
<input id="delete-button" type="button" value="Delete">
</body>
</html>


More research got me to an answer: "this" does not always refer to the
object for which you work. Specifically when called by an event
handler the called function will have "this" set to the control for
whom the event was generated (e.g., button). The original objective
(having a controller object) can be resolved by one level of
indirection:

<html>
<head>
<script>
function initialize() {
var controller = new ViewController();
document.getElementById("delete-button").onclick = function() {
controller.handleDeleteButtonClicked();
}
}

/* constructor */
function ViewController() {
this.foo = "bar";
}

/* delete button handler */
ViewController.prototype.handleDeleteButtonClicked = function() {
window.alert("delete clicked, this' constructor=" +
this.constructor);
};

</script>
</head>
<body onload="javascript:initialize();">
<input id="delete-button" type="button" value="Delete">
</body>
</html>
 
E

ensemble

VK said:
ensemble said:
I'm trying to utilized a more object-oriented approach to managing
window events in javascript. Thus, I am creating a "controller" object
to handle events and interact with the server.

IMHO your code looks more as an attempt to reproduce other languages
weaknesses and workarounds in javascript. The javascript event model
has enough of its own headaches to add Java's or C++'s ones into it ;-)

<html>
<head>
<title> make KISS - then OOP ! </title>
<meta http-equiv="Content-Type"
content="text/html; charset=iso-8859-1">

<script type="text/javascript">

function EventListener(obj) {

// Lightweight constructor protection:
if (((window) && (this == window))
|| (!obj) || (!obj.tagName)) {
return new Boolean(false);
}

obj.JSInstance = this;

this.foo = 'foo';

for (var i=1; i<arguments.length; i++) {
obj[arguments] = EventListener[arguments];
}
}

EventListener.onmouseover = function() {
this.style.backgroundColor = 'yellow';
}

EventListener.onmouseout = function() {
this.style.backgroundColor = '';
}

EventListener.onclick = function() {
alert(this.JSInstance.foo);
}


function init() {
new EventListener(document.getElementById('btnAdd'),
'onmouseover', 'onmouseout');

new EventListener(document.getElementById('btnEdit'),
'onclick' );

new EventListener(document.getElementById('btnDelete'),
'onmouseover', 'onmouseout', 'onclick' );
}


window.onload = init;
</script>
</head>

<body>
<button id="btnAdd" type="button">Add</button>
<button id="btnEdit" type="button">Edit</button>
<button id="btnDelete" type="button">Delete</button>

</body>
However, I apparently
don't fully understand what "this" refers to.

[this] refers to the *current object* (or by ECMAScript specs it points
to "the object pointed by [this] keyword", which is cool to know but
not very helpful :)

Current object can be:
1) Global object (most of the time)
2) New object instance (in constructor)
3) Object instance owning the called method (more rarely than it should
IMHO)
4) Other object instance transferred by call() or apply() methods
5) Equivalent of *default object* in with (this) {...} construct
6) DOM element received the event in intrinsic method handlers.

By the rules of good show I placed your case at the very end :)


Hi VK -
I'm curious to more about your comment "IMHO your code looks more as an
attempt to reproduce other languages weaknesses and workarounds in
javascript." I haven't done a lot of javascript progamming. However,
I'm interested in apply object oriented approaches to this environment.
GUIs were originally developed using OO languages and it seems natural
to me to apply the same principals here. I'm sure you are aware of all
of the literature being introduced right now on the topic of OO and
javascript development.

It sounds like you might have taken this path yourself and found it was
more frustrating than beneficial? Would be interested in your views....
 
T

TC

TC said:
Uh, say what? GUIs existed before the notion of object oriented
languages had even been thought of!

Hmm, perhaps I should qualify that. Certainly there were graphic
terminals back in the 1960's. These could display (and allow for entry
of) information, somewhat like a modern GUI. But they did not have
mice, or allow for common modern GUI features like drag & drop. So I
guess they were not GUIs in the modern sense of the word.

TC (MVP MSAccess)
http://tc2.atspace.com
 
M

Michael Winter

ensemble wrote:

[snip]
I'm curious to more about your comment "IMHO your code looks more as
an attempt to reproduce other languages weaknesses and workarounds in
javascript."

There is a growing movement to make ECMAScript and its implementations
look like other languages - Python, for example. One problem is that
these wrappers invite the assumption that because the two languages now
look like one another, they act in the same way, too. This reasoning is
flawed and unproductive: understanding the real, underlying language is
the only way to really appreciate behaviour.
I haven't done a lot of javascript progamming. However, I'm
interested in apply object oriented approaches to this environment.

Do keep in mind the practicality of OO and ECMAScript. There is
sometimes little point in developing an OO solution to a problem, and
doing so only adds bloat. If there is a real return on investment from
taking an OO path, then by all means do so, but think if the benefits
are marginal.

[snip]

Mike
 
J

John W. Kennedy

TC said:
Hmm, perhaps I should qualify that. Certainly there were graphic
terminals back in the 1960's. These could display (and allow for entry
of) information, somewhat like a modern GUI. But they did not have
mice, or allow for common modern GUI features like drag & drop. So I
guess they were not GUIs in the modern sense of the word.

They had light pens that were functionally equivalent to mice, and used
drag and drop in graphics applications (drag the chair from the
furniture library to the conference room, drag the resistor from the
component library and insert it in the circuit, etc., etc.). They were
much too expensive to use as word processors, etc..
 
R

RobG

TC said:
Uh, say what? GUIs existed before the notion of object oriented
languages had even been thought of!

Without a clear definition of what constitutes a GUI and an OO
language, that's not much more than idle boast. While the definitional
debate in regard to GUIs could rage for ages, there seems to be
agreement that SIMULA I (1962) was the first OO language.

<URL:
http://heim.ifi.uio.no/~kristen/FORSKNINGSDOK_MAPPE/F_OO_start.html >

Probably the first interface that implemented most of the fundamental
principles of a modern GUI was oNLine, creation of which started in
1962, although it wasn't revealed to the world until 1968.

<URL: http://www.kernelthread.com/mac/oshistory/2.html >

Therefore to claim that GUI's predate OO languages seems incorrect,
though I'd like to note that you don't need an OO language to write OO
programs, or to write a GUI.
 
T

TC

John said:
They had light pens that were functionally equivalent to mice, and used
drag and drop in graphics applications (drag the chair from the
furniture library to the conference room, drag the resistor from the
component library and insert it in the circuit, etc., etc.). They were
much too expensive to use as word processors, etc..

Indeed, I'd forgotten the light pens! I now remember some cases where
you could point & click by using those pens - sort of like a modern
touchscreen. Well before OO existed :)

TC (MVP MSAccess)
http://tc2.atspace.com
 
V

VK

Hmm, perhaps I should qualify that. Certainly there were graphic
terminals back in the 1960's. These could display (and allow for entry
of) information, somewhat like a modern GUI. But they did not have
mice, or allow for common modern GUI features like drag & drop. So I
guess they were not GUIs in the modern sense of the word.

IMHO GUI is Graphical User Interface, nothing less but nothing more. It
is not in relevance to OOP. That can be OOP program w/o GUI and GUI
program w/o OOP.
I don't dare to go back to the happy 60's :) but back in 1982 I was
impressed by ArtStudio program - I don't remember producers - on my ZX
Spectrum (1MHz, 64Kb RAM). This color bitmap picture editor had
drop-down menus, drag/drop features, context-dependant screen pointer
(manipulated by joystick). Of course all of this was written in direct
processor commands (the only language which worth anything :)) But I
don't think that we should take the ZX Spectrum processor commands set
as a sample of an OOP language :)

Object Oriented Programming assumes that you program manipulates with
different objects having different properties. And if you don't see any
suitable object around, you take the most convenient object among the
existing ones and you build a new custom object on its basis.

That's it: all the rest is propaganda, so students would not just learn
OOP thinking, but also would "sit on the needle" of a particular
OOP-capable language (because these are IDE's, patches and updates they
will buy later - and future software they will write for the glory of
IDE producers). I don't see any lack of "pushers" in higher schools and
in bookstores.

That is all IMHO without any claims to be "universally true" or to be
true at all (though I believe in the latter).
 
V

VK

ensemble said:
I'm curious to more about your comment "IMHO your code looks more as an
attempt to reproduce other languages weaknesses and workarounds in
javascript." I haven't done a lot of javascript progamming. However,
I'm interested in apply object oriented approaches to this environment.
GUIs were originally developed using OO languages and it seems natural
to me to apply the same principals here. I'm sure you are aware of all
of the literature being introduced right now on the topic of OO and
javascript development.
It sounds like you might have taken this path yourself and found it was
more frustrating than beneficial?

"I am doing what I like. What I like is OOP. You don't like what I am
doing. You don't like OOP."

As I don't have Dodgson's (Caroll) syllogistic talents, I better stay
on plain words :)

As my grand dad used to say: "Do not mix God's gift and an omelet" :)
Other words let's us do not mix two all different things together i)
OOP paradigm and ii) language specific algorithms to accomplish this
paradigm. A good amount of "Really Truly Proper JavaScript OOP"-like
books have one default which renders them into rather confusing
sources. Namely a lot of them are written with the statement "the
OOP-ready language I already know == OOP" taken for true; as the result
the whole subject gets seamlessly substituted from "OOP in JavaScript"
to "Emulation of *** language in JavaScript".
From the positions of OOP itself one could spell your task as: "I need
new class of buttons extending the default DOM button. Each instance
has to have ..., ... properties and react on ..., ... events in the
following way:... I want to be able to create new classes of buttons
based on my class: with even more properties but also with all
properties inherited from the underlying classes".

That is all what OOP has to say on the subject.
Any "controllers", "listeners", "dispatcher", "do this, not that" is
not OOP: these are specific tools to implement OOP paradigm in a
specific language environment. In the particular the idea of controller
is most probably coming from C++ (second best guess - Java). In these
languages objects "do not hear, do not see" any events until one teach
them to do so over added interfaces. And with thousands of objects each
firing dozens of types of custom events with a rate up to single system
tick you need an event queue and some dispatcher so things wouldn't go
to hell completely.
JavaScript doesn't need any of this. Sure you can implement controllers
and even centralized dispatcher by language tools, but it would be
higher level duplicate implementation atop of existing lower level
implementation (== not needed).

P.S. IMHO
P.P.S. I love OOP :) and I'm using nothing but OOP in high level
languages programming.
 
J

John G Harris

3) Object instance owning the called method (more rarely than it should
IMHO)
<snip>

If you do
b.f = a.f;
when f is a function object, is it a or b that now owns the
function?

John
 
V

VK

John said:
If you do
b.f = a.f;
when f is a function object, is it a or b that now owns the
function?

No one: until this function is called. And then it's owned by the
calling object instance (unless "incontinence of [this]" problem say
for timed calls). It is not an exact analogy, but it may help to think
of 100 Java objects having static method f(). Which one of the hundred
"owns" f() ?

I did not mean exactly that in my first post, but it is covered as well
by "reproduce other languages weaknesses and workarounds in
javascript". The question of "b.f = a.f", once so popular in Java
topics is simply not applicable to JavaScript. It doesn't use
(internally) OID stamping for members as say C++ or Java do. That is
why a good OOP style for JavaScript used to be: "if a method will
appertain to a number of instances and if it doesn't need to store
instance-specific info: then make it static". You create function only
once and then reference it in instances. At the most wild times of
Browser Wars it still seemed natural and resource wise to:

function f() {
}

function myConstructor() {
this.method = f;
}

That was this way until C++'er came and started to teach "ignorants"
what the real OOP is about :) Now if some constructor doesn't have at
least couple of closures (desirable nested ones) and inner functions
then it is not OOP but some crap. And of course no static methods: for
1000 objects we will replicate 1000 anonymous functions. Surely all
this eats memory and leaks like an old barn's roof on IE: but no
sacrificion is big enough for Real OOP :)
 
J

John W. Kennedy

TC said:
Indeed, I'd forgotten the light pens! I now remember some cases where
you could point & click by using those pens - sort of like a modern
touchscreen. Well before OO existed :)

The first two generations of 3270 could use light pens for clicking, but
couldn't drag or draw. Light pens generally fell out of use for
ergonomic reasons.
 
J

John G Harris

VK said:
No one: until this function is called. And then it's owned by the
calling object instance

Nonsense. When your code does b.f() the code inside f starts with
this === b
this goes back to its previous value when f finishes.

It's as simple as that. Ownership has nothing to do with it.

(unless "incontinence of [this]" problem say
for timed calls). It is not an exact analogy, but it may help to think
of 100 Java objects having static method f(). Which one of the hundred
"owns" f() ?

I did not mean exactly that in my first post, but it is covered as well
by "reproduce other languages weaknesses and workarounds in
javascript". The question of "b.f = a.f", once so popular in Java
topics is simply not applicable to JavaScript. It doesn't use
(internally) OID stamping for members as say C++ or Java do.
<snip>

You've been reading the wrong web pages. OIDs in C++ - good grief!


John
 
V

VK

If you do
Nonsense. When your code does b.f() the code inside f starts with
this === b
this goes back to its previous value when f finishes.
It's as simple as that. Ownership has nothing to do with it.

"Ownership" is not a programming category at all. I used this term from
your post poetically and I put it into quotes at the end ("transferred
meaning" quotes).

But you are right pointing to an omission:
"No one: until this function is called. And then it's owned by the
You've been reading the wrong web pages. OIDs in C++ - good grief!

You've been learning from wrong prof's :)
OID's are the basic for class-based languages - once again - in the
internal mechanics.
But we can stay on the level of the language itself by saying that
JavaScript doesn't implement encapsulation unlike C++ or say Java do.
 
V

VK

If you do
"No one: until this function is called. And then it's owned by the
calling object instance <ins>during the call</ins>." - that will be
better.

I maybe have to explain it better because it is one of important
aspects of JavaScript OOP (completely missed in 99.9% of relevant
books) .

* JavaScript objects do not have "owner / owned" relations as such. *

It is not in any relevance of what inheritance is used: a classy
emulated one or a prototype-based one. JavaScript do not use
encapsulation (doesn't use OID stamping) and internally it is a pure
ideal communism :) - everyone can take anything it wants but it cannot
take it into exclusive use.
Instead JavaScript uses the backward lookup chain: say if you call
a.f(), the engine finds [a] and if it contains named property [f]
containing in turn a reference to some function, [a] becomes a
"temporary owner" of that function, but only for the period of the
function execution. That can be 1,000 other objects referencing said
function and no one is more "owner" than [a]. That is why "who owns
this function (method)" is pointless in JavaScript. With the same
success one could ask, "what is the temperature of the darkness" or
similar.

If I started on that, I would like to point to another common
misunderstanding, which is IMHO in relation with "who owns who".

I mean the constructs
function name() {}
and
var name = function(){};

First of all, 1) the common mistake is that they are equivalent. 2)
Second - not a mistake, but misconception maybe - is that
MyObject.method = function(){};
or at least
MyObject.prototype.method = function(){};
do establish some special "ownership" relations between MyObject and
the assigned function.

1)
function myFunction() {}
and
var myFunction= function(){};
are not equivalent and their evaluation leads to very different
results. In the first case we are creating named function myFunction
(one object). In the second case we are creating anonymous function
(identified internally by an unique dispid), then we are creating
variable myFunction and then we are assigning a reference of that newly
created anonymous function to the variable myFunction (two different
objects).
From my previous experience I know that the understanding of this
difference creates difficulties even for most experienced javascript
programmers. (see
<http://groups.google.com/group/comp.lang.javascript/msg/dfb09051f1dfb1c8>)

Maybe some pictures will help this time:

<http://www.geocities.com/schools_ring/blogs/Image1.gif>
- shows the stack state for var something = function(){}

<http://www.geocities.com/schools_ring/blogs/Image2.gif>
- shows the stack state for function something(){}

<http://www.geocities.com/schools_ring/blogs/Image3.gif>
- shows the stack state for var something = function name(){}
(The latter syntax beyond my humble understanding but recently I see it
increasingly in software products clamed to be made by professional
developers. Must be another "discover" in JavaScript made by some
C++'ish writer. So I just added it here so at least readers of this
article would not look silly in their codes.)

2) Now it is easy to see why
MyObject.method = function(){};
doesn't create any special relations between MyObject and function(){};

We are simply adding a reference to anonymous function to the named
property "method". The function itself remains the same "free cat" as
it was before. So *functionally* it is exact equivalent of:
function something(){}
MyObject.method = something;
 
M

Michael Winter

VK wrote:

[snip]
I mean the constructs
function name() {}
and
var name = function(){};

First of all, 1) the common mistake is that they are equivalent.

Exactly equivalent? No, certainly not. However, in most ways that
matter, they are the same.

[snip]
function myFunction() {}
and
var myFunction= function(){};
are not equivalent and their evaluation leads to very different
results.

Both establish a new property, myFunction, within the variable object of
the "enclosing" execution context. That is to say that both create a
local variable. Both create a function object, and that object has the
same formal arguments, the same scope chain, the same properties,
values, and prototype chain, and the same function body. The only
difference between them is /when/ the function object is created: this
doesn't occur for the latter until the function expression is evaluated
during execution (assuming it even is evaluated).

As I wrote above, the two forms aren't exactly the same, but they are in
most ways that matter.
In the first case we are creating named function myFunction (one
object).

When a function declaration is present within the body of some function
(F), a new local variable is created just before execution of F with the
name given in that declaration (myFunction) and is assigned the function
object that results from evaluating the function declaration. It is a
two-step process.
In the second case we are creating anonymous function (identified
internally by an unique dispid),

How any object is identified internally is of no relevance to anyone (at
least not to anyone who isn't embedding a scripting engine into an
application). Certainly, how Microsoft might do it provides little
insight to any other implementation.
then we are creating variable myFunction and then we are assigning a
reference of that newly created anonymous function to the variable
myFunction (two different objects).

You have that backwards. After all function declarations have been
processed, any variable declarations (var statements) within the body of
a function cause new properties to be added to the variable object each
with the value, undefined. If the initialiser is evaluated during the
course of normal execution, only then will the right-hand side of the
assignment expression be assigned to the variable. It is at this stage
that the function expression is evaluated.

[snip]
<http://www.geocities.com/schools_ring/blogs/Image1.gif>
- shows the stack state for var something = function(){}

<http://www.geocities.com/schools_ring/blogs/Image2.gif>
- shows the stack state for function something(){}

<http://www.geocities.com/schools_ring/blogs/Image3.gif>
- shows the stack state for var something = function name(){}

How is that useful or helpful to anyone? What pertinent information do
you even think it shows? As far as I can see, all it demonstrates is the
choices that Microsoft Script Debugger makes when referring to functions.
(The latter syntax beyond my humble understanding but recently I see
it increasingly in software products clamed to be made by
professional developers. Must be another "discover" in JavaScript
made by some C++'ish writer. So I just added it here so at least
readers of this article would not look silly in their codes.)

Whether they look silly or depends upon how they use the latter.

The identifier in a function expression can only be used within the body
of that function. It is added to the scope chain of the "enclosing"
execution context before creation of the function object, removed
afterwards, and is a reference to the newly created function. It is,
effectively, a local variable, therefore using it outside of the
function body as if the expression was a function declaration is illegal.

[snip]

Mike
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,763
Messages
2,569,563
Members
45,039
Latest member
CasimiraVa

Latest Threads

Top