Saturday, September 03, 2005

How to understand the javascript class model? - JavaScript

How to understand the javascript class model? - JavaScript:


In general, when all data members 'public', methods should be added via
the prototype object. This produces only one function object for each
method. With the code above, each new object will create new functions
even though they could be shared.

function Class() {
this.member = null;
this.event = null;
}
Class.prototype.memberFunction = function() {
alert('memberFunction: ' + this.member);
this.callEvent();
alert('after call');
};
Class.prototype.callEvent = function() {
alert('callEvent: ' + this.event);
if('function' == typeof this.event) {this.event();}
};

Creating methods as you did should normally be used when utilising
'private' members:

function MyObject() {
var private = 'value';

this.method = function() {
alert(private);
};
}

var o = new MyObject();

o.method(); // 'value'
o.private; // error

[snip]

>
>

The value of id and name attributes should never be used as global
variables. Many browsers do not support this.

var element;

if(document.getElementById) {
element = document.getElementById('hello');
}
if(element) {
element.onclick = obj.memberFunction;
}

> I try to define a javascript class [...]

There's no such thing. Javascript uses a prototype-based inheritance
model, where your objects use other objects as a basis for their
features and behaviours. Your Class, above, is a constructor function
that when executed, can be used to initialise an object instance and
augment the object that results from the instantiation.

> When I call the function: obj.memberFunction(); the event handler was
> fired and alert a message ('event'). But when I try to use a button
> to fire the event, it doesn't work.

The this operator exists everywhere (unlike in other languages), and as
such, its value is determined by how code is executed.

In 'global' scope



the this operator refers to the global object (usually referred to as
window). Similarly, functions that are called directly have the same value:

var o = {
method : function() {alert(this == window);}
},
f = o.method;

f(); // true; this refers to global object
o.method(); // false; same function object,
// but this now refers to 'o'

Notice that in this latter case, the this operator refers to the object
before the last dot operator: 'o'. A similar thing happens in your case.
When the browser fires the event listener, it does so as though it did

buttonElement.onclick()

In other words, the this operator refers to the BUTTON element.

To solve this, you need to keep a reference to the object that you can
use later. One way is to use the 'private' member form I showed earlier:

function Class() {
var instance = this;

this.member = null;
this.event = null;

this.memberFunction = function() {
alert('memberFunction: ' + instance.member);
instance.callEvent();
alert('after call');
};
}
Class.prototype.callEvent = function() {
alert('callEvent: ' + this.event);
if('function' == typeof this.event) {this.event();}
};

Looking at the implementation of the memberFunction member, you can see
that it's defined in terms of the instance private variable. Even when
the this operator will refer to the BUTTON element, instance will still
refer to the object. When the method calls the callEvent method, it does
so through the object reference, so the this operator will refer to the
object again.

Hope that helps,
Mike

0 Comments:

Post a Comment

<< Home