'this', event handlers, and namespaces

J

Jeff Bigham

Hi,

Consider the following simplified code in which Foo is used as a
'namespace':

var Foo = {
doAlert: function() {
alert('hello');
},
myEventHandler: function(e) {
this.doAlert();
}
}

document.addEventListener('keydown', Foo.doAlert, false);


This gives me an error because when responding to the event, the
object 'this' is the document because that's what I've attached the
event handler to. I know I could just replace 'this' with "Foo.' but
my understanding is that I take a performance hit every time I make
such a global reference. And, since I'm developing a large web
application in Javascript, I'd like to avoid unnecessary performance
hits when possible.

Anyone know what is the accepted standard of what to do in this case?

Thanks!
Jeff
 
R

RobG

Hi,

Consider the following simplified code in which Foo is used as a
'namespace':

var Foo = {
doAlert: function() {
alert('hello');
},
myEventHandler: function(e) {
this.doAlert();
}

}

document.addEventListener('keydown', Foo.doAlert, false);

This gives me an error because when responding to the event, the
object 'this' is the document because that's what I've attached the
event handler to. I know I could just replace 'this' with "Foo.' but
my understanding is that I take a performance hit every time I make
such a global reference. And, since I'm developing a large web
application in Javascript, I'd like to avoid unnecessary performance
hits when possible.

Anyone know what is the accepted standard of what to do in this case?

Try this thread:

Subject: pseudo-namespacing in JavaScript
<URL:
http://groups.google.com.au/group/c...do-namespacing+in+JavaScript#ce45e485506c4a92
 
J

jdd

Hi,

Consider the following simplified code in which Foo is used as a
'namespace':

var Foo = {
  doAlert: function() {
    alert('hello');
  },
  myEventHandler: function(e) {
    this.doAlert();
  }

}

document.addEventListener('keydown', Foo.doAlert, false);

This gives me an error because when responding to the event, the
object 'this' is the document because that's what I've attached the
event handler to.  I know I could just replace 'this' with "Foo.' but
my understanding is that I take a performance hit every time I make
such a global reference.  And, since I'm developing a large web
application in Javascript, I'd like to avoid unnecessary performance
hits when possible.

Anyone know what is the accepted standard of what to do in this case?

Thanks!
Jeff

I don't know if it's the accepted standard of what to do, but you
could do something like:

var Foo = {
  doAlert: function() {
    alert('hello');
  },
  myEventHandler: (function(t) {
that = t;
return function(e) {
    that.doAlert();
};
})(this)
}

I don't think this would be avoiding a performance hit though, and you
probably shouldn't listen to my advice as I'm still a bit green on
javascript. Additionally, I think the proper solution depends on what
exactly you're trying to do.
 
T

Thomas 'PointedEars' Lahn

Jeff said:
Consider the following simplified code in which Foo is used as a
'namespace':

var Foo = {
doAlert: function() {
alert('hello');
},
myEventHandler: function(e) {
this.doAlert();
}
}

document.addEventListener('keydown', Foo.doAlert, false);

Probably you meant to write

document.addEventListener('keydown', Foo.myEventHandler, false);

instead, as there is no `this' in Foo.doAlert().
This gives me an error because when responding to the event, the
object 'this' is the document because that's what I've attached
the event handler to.

_added_ event _listener_ to

This is a FAQ, and the solution is simple:

document.addEventListener(
'keydown',
function(e) { Foo.myEventHandler(e) },
false);

That said, by convention only names of properties that refer to
constructors, and identifiers of constant primitive values, should begin
with a capital letter.
I know I could just replace 'this' with "Foo.' but my understanding
is that I take a performance hit every time I make such a global reference.

That is correct, as no identifier resolution is required for the `this'
value of the execution context. However, the evaluation loop would be very
short; the main issue here is maintainability: You really do not want to do
search and replace when you have to rename `Foo' (and you should do that).
And, since I'm developing a large web application in Javascript, I'd
like to avoid unnecessary performance hits when possible.

Good thinking, though.
Anyone know what is the accepted standard of what to do in this case?

There is no accepted standard about it, only common sense guided by the text
of the ECMAScript Specification and by the reality of its implementations.


PointedEars
 
T

Thomas 'PointedEars' Lahn

jdd said:
Consider the following simplified code in which Foo is used as a
'namespace':

var Foo = {
doAlert: function() {
alert('hello');
},
myEventHandler: function(e) {
this.doAlert();
}
}

document.addEventListener('keydown', Foo.doAlert, false);

This gives me an error because when responding to the event, the
object 'this' is the document because that's what I've attached the
event handler to. [...]

Anyone know what is the accepted standard of what to do in this case?

I don't know if it's the accepted standard of what to do, but you
could do something like:

var Foo = {
doAlert: function() {
alert('hello');
},
myEventHandler: (function(t) {
that = t;
return function(e) {
that.doAlert();
};
})(this)
}

This code does not address the problem at all. In the above scenario, the
`myEventHandler' property would be assigned a reference to a Function object
that calls the doAlert() method of the *Global Object* (or the object
referenced by the `that' property of an object in the scope chain, see
below) instead of the object referred to by `Foo'. A TypeError exception on
event is likely as the Global Object (or that object) is unlikely to have a
method of that name. It is semantically equal to

that = this;
var Foo = {
doAlert: function() {
alert('hello');
},
myEventHandler: function(e) {
that.doAlert();
};
};

Also, the undeclared `that' identifier is inherently error-prone.

Please trim your quotes as recommended e.g. in the FAQ Notes.


PointedEars
 
J

Jorge

Hi,

Consider the following simplified code in which Foo is used as a
'namespace':

var Foo = {
  doAlert: function() {
    alert('hello');
  },
  myEventHandler: function(e) {
    this.doAlert();
  }

}

document.addEventListener('keydown', Foo.doAlert, false);

This gives me an error because when responding to the event, the
object 'this' is the document because that's what I've attached the
event handler to.  I know I could just replace 'this' with "Foo.' but
my understanding is that I take a performance hit every time I make
such a global reference.  And, since I'm developing a large web
application in Javascript, I'd like to avoid unnecessary performance
hits when possible.

Anyone know what is the accepted standard of what to do in this case?

Thanks!
Jeff

<html lang="en"><head>
<title>untitled</title></head><body>
<script>
var c= ": No closure";
(function () {
var d, e, c= ": anon f closure !";;
var y= function (p) { return document.createElement(p) };
var z= function (p) {
document.body.appendChild(y('br'));
return document.body.appendChild(p);
};
var x= function (p) { (z(y('text'))).innerHTML= p };

var foo= function (e) {
var c= ": foo closure !";
var me= arguments.callee;
me.doAlert= function() { x(this.src+': onClick'+c) };
var doAlert= function() { x(this.src+': onMouseUp'+c) };

//function object method : foo.doAlert()
e.onclick= me.doAlert;
//foo local var:
e.onmouseup= doAlert;
//anonymous function:
e.onmouseover= function () { x(this.src+': onMouseOver'+c) };
return e;
};

foo.too= function () { x(this.src+': onMouseOut'+c) };

(e= foo(z(y('img')))).src="http://tinyurl.com/6nhepj"
//anonimous function object method 2:
e.onmouseout= foo.too;
(d=z(y('img'))).src="http://tinyurl.com/5ehxv5"
//anonimous function object method 2:
d.onmouseout= foo.too;
d.onmouseover= e.onmouseover;
})();
</script></body></html>
 
J

Jorge

Hi,

Consider the following simplified code in which Foo is used as a
'namespace':

var Foo = {
  doAlert: function() {
    alert('hello');
  },
  myEventHandler: function(e) {
    this.doAlert();
  }

}

document.addEventListener('keydown', Foo.doAlert, false);

This gives me an error because when responding to the event, the
object 'this' is the document because that's what I've attached the
event handler to.  I know I could just replace 'this' with "Foo.' but
my understanding is that I take a performance hit every time I make
such a global reference.  And, since I'm developing a large web
application in Javascript, I'd like to avoid unnecessary performance
hits when possible.

Anyone know what is the accepted standard of what to do in this case?

Thanks!
Jeff

<html lang="en"><head>
<title>untitled</title></head><body>
<script>
var c= ": No closure";
(function () {
var d, e, c= ": anon f closure !";;
var y= function (p) { return document.createElement(p) };
var z= function (p) { return document.body.appendChild(p) };
var x= function (p) {
z(y('br'));
(z(y('text'))).innerHTML= p;
};

var foo= function (e) {
var c= ": foo closure !";
var me= arguments.callee;
me.doAlert= function() { x(this.src+': onClick'+c) };
var doAlert= function() { x(this.src+': onMouseUp'+c) };

//function object method : foo.doAlert()
e.onclick= me.doAlert;
//foo local var:
e.onmouseup= doAlert;
//anonymous function:
e.onmouseover= function () { x(this.src+': onMouseOver'+c) };
return e;
};

foo.too= function () { x(this.src+': onMouseOut'+c) };

(e= foo(z(y('img')))).src="http://tinyurl.com/6nhepj"
//anonimous function object method 2:
e.onmouseout= foo.too;

(d=z(y('img'))).src="http://tinyurl.com/5ehxv5"
//anonimous function object method 2:
d.onmouseout= function () { x(this.src+': onMouseOut'+c) };
d.onmouseover= function () { x(this.src+': onMouseOver'+c) };
d.onclick= function() { x(this.src+': onClick'+c) };
d.onmouseup= function () { x(this.src+': onMouseUp'+c) };

(d=z(y('img'))).src="http://tinyurl.com/5j84u6"
//anonimous function object method 2:
d.onmouseout= e.onmouseout;
d.onmouseover= e.onmouseover;
d.onclick= e.onclick;
d.onmouseup= e.onmouseup;

})();
</script></body></html>
 
T

Thomas 'PointedEars' Lahn

Jorge said:
Anyone know what is the accepted standard of what to do in this case?
[...]

<html lang="en"><head>
<title>untitled</title></head><body>
<script>
var c= ": No closure";
(function () {
var d, e, c= ": anon f closure !";;
var y= function (p) { return document.createElement(p) };
var z= function (p) { return document.body.appendChild(p) };
var x= function (p) {
z(y('br'));
(z(y('text'))).innerHTML= p;
};

var foo= function (e) {
var c= ": foo closure !";
var me= arguments.callee;
me.doAlert= function() { x(this.src+': onClick'+c) };
var doAlert= function() { x(this.src+': onMouseUp'+c) };

//function object method : foo.doAlert()
e.onclick= me.doAlert;
[...]

Sorry, this does not come even close to an approach that could make it to
standard procedure, much less to the standards-compliant approach that the
OP was following already. It is not even Valid markup to begin with:

http://validator.w3.org/


PointedEars
 
J

Jeff Bigham

There is no accepted standard about it, only common sense guided by the text
of the ECMAScript Specification and by the reality of its implementations.

Thanks. What you suggested worked well.

-Jeff
 
B

Bjoern Hoehrmann

* Jeff Bigham wrote in comp.lang.javascript:
Consider the following simplified code in which Foo is used as a
'namespace':

var Foo = {
doAlert: function() {
alert('hello');
},
myEventHandler: function(e) {
this.doAlert();
}
}

document.addEventListener('keydown', Foo.doAlert, false);

You would have to call the event handler method 'handleEvent' and pass
the object rather than the function to addEventListener, i.e., like so:

var Foo = {
doAlert: function() {
alert('hello');
},
handleEvent: function(e) {
this.doAlert();
}
}

document.addEventListener('keydown', Foo, false);

With your approach `this` should always be bound to e.currentTarget.
 

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,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top