Can't call one function from another in a class

  • Thread starter Joel Whitehouse
  • Start date
J

Joel Whitehouse

The idea is to have a class wrapper for a single variable. Whenever the
variable is set with a new value through the function setValue(), I want
the event function "onchange" to be triggered.

Here's my code:

---------------------------------------
function Field()
{ var that = this;
var _data = null;

//Events
this.onchange = function(d){};

this.setData = function(d)
{
_data = d;

//I've tried calling onchange() so many ways. Documented here
//are the errors each attempt produces

//IE: "Object expected"
//FF: "that.onchange is not a function"
that.onchange(d);

//IE: "Object expected"
//FF: "this.onchange is not a function"
this.onchange(d);

//IE: "Object expected"
//FF: "onchange is not defined"
onchange(d);
};

this.getData = function()
{
return _data;
};
}//end of Field()
---------------------------------------




For some reason I can't access the onchange() function from setData().
How can I fix that? Thanks so much in advance!

-Joel
 
P

Peter Michaux

function Field() {
var that = this;
var _data = null;

//Events
this.onchange = function(d){};

this.setData = function(d) {
_data = d;

//I've tried calling onchange() so many ways. Documented here
//are the errors each attempt produces

//IE: "Object expected"
//FF: "that.onchange is not a function"
that.onchange(d);

The line above seems to work
//IE: "Object expected"
//FF: "this.onchange is not a function"
this.onchange(d);

The line above should work if you call it like this

var f = new Field();
f.setData(123);
//IE: "Object expected"
//FF: "onchange is not defined"
onchange(d);

The line above should not work
};

this.getData = function()
{
return _data;
};
}//end of Field()

With the above code you are defining the setData, getData and onChange
functions for each instance of Field. There is a more efficient way to
make a constructor function called Field so that each instance will
have these functions.

function Field() {
// constructor content
}
Field.prototype.onchange = function(d) {
// do stuff
};
Field.prototype.setData = function(d) {
this.data = d;
this.onchange(d);
};
Field.prototype.getData = function() {
return this.data;
};

With the above the functions onchange, setData and getData are only
defined once for the prototype of all field instances and are shared/
reused.

If you don't care about the "constructor" property of objects then you
could write this more compactly

function Field() {
// constructor content
}
Field.prototype =
onchange: function(d) {
// do stuff
},
setData: function(d) {
this.data = d;
this.onchange(d);
},
getData: function() {
return this.data;
}
};

Peter
 
P

Peter Michaux

The line above seems to work


The line above should work if you call it like this

var f = new Field();
f.setData(123);


The line above should not work



With the above code you are defining the setData, getData and onChange
functions for each instance of Field. There is a more efficient way to
make a constructor function called Field so that each instance will
have these functions.

function Field() {
// constructor content}

Field.prototype.onchange = function(d) {
// do stuff};

Field.prototype.setData = function(d) {
this.data = d;
this.onchange(d);};

Field.prototype.getData = function() {
return this.data;

};

With the above the functions onchange, setData and getData are only
defined once for the prototype of all field instances and are shared/
reused.

If you don't care about the "constructor" property of objects then you
could write this more compactly

function Field() {
// constructor content}

Field.prototype =

Make that

Field.prototype = {
 
J

Joel Whitehouse

Thanks, Peter.

Is there any way for the data variable to be private while still using
Field.prototype to prevent functions from being instantiated too much?
I don't want myField.data to be a syntactically valid method of changing
the data, if at all possible.

Thanks again for all your help!

-Joel
 
P

Peter Michaux

Thanks, Peter.

Is there any way for the data variable to be private while still using
Field.prototype to prevent functions from being instantiated too much?
I don't want myField.data to be a syntactically valid method of changing
the data, if at all possible.

You can make data a pseudo private variable

function Field() {
// constructor content
}

(function() {
var data;
Field.prototype.onchange = function(d) {
// do stuff
};
Field.prototype.setData = function(d) {
data = d;
this.onchange(d);
};
Field.prototype.getData = function() {
return data;
};
})();

With the more compact version

function Field() {
// constructor content
}

(function() {
var data;
Field.prototype = {
onchange: function(d) {
// do stuff
},
setData: function(d) {
data = d;
this.onchange(d);
},
getData: function() {
return data;
}
};
})();

Alternately you could write this as the following which seems the most
Crockford-ish

function Field() {
// constructor content
}

Field.prototype = (function() {
var data;
return {
onchange: function(d) {
// do stuff
},
setData: function(d) {
data = d;
this.onchange(d);
},
getData: function() {
return data;
}
};
})();



Just in case this is new to you

(function(){
// stuff
})();

This has been dubbed "the module pattern" and was promoted by Cornford
and Crockford.


http://www.litotes.demon.co.uk/js_info/private_static.html

http://www.crockford.com/javascript/private.html

This recent YUI article is more recent.

http://yuiblog.com/blog/2007/06/12/module-pattern/

I use this pattern but I don't really believe in using this pattern
unless there is a darn good reason. Just trying to simulate privacy is
not a good reason to me. I think the underscore convention to indicate
intended privacy of a public property is pretty good and is less
complex. There really isn't such a thing as a private variable in
JavaScript anyway.

Using the module pattern to keep the global window object clean is a
good reason, however.

Peter
 

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

Forum statistics

Threads
473,780
Messages
2,569,611
Members
45,276
Latest member
Sawatmakal

Latest Threads

Top