From: nick on
So, I was using the good old module pattern, and I had some generic
key handling code like this...

window.myApp = {}; // so this example will run
myApp.keys = (function(){

const down = 0, up = 1, callbacks = {};
var initted = false;

// public methods
return {
register : function (key, onPress, onRelease) {
if (!initted) init();
key = key === +key ? key :
(key+'_').toUpperCase().charCodeAt(0);

callbacks[key] = [onPress, onRelease];
},
unregister : function (key) { delete callbacks[key] }
}

// private methods
// ...
})();

.... and something hit me. You see that anonymous function calling
itself (closure) all the time. Wouldn't it look a lot cleaner like
this...

myApp.keys = new function(){

const down = 0, up = 1, callbacks = {};

var initted = false;

// public methods

this.register = function (key, onPress, onRelease) {
if (!initted) init();
key = key === +key ? key :
(key+'_').toUpperCase().charCodeAt(0);
callbacks[key] = [onPress, onRelease];
}

this.unregister = function (key) { delete callbacks[key] }

// private methods

function onKey(evt, fn) {
evt = evt || window.event; //IE reports window.event
var kc = evt.chrCode || evt.keyCode, cb = callbacks[kc];
if (cb && typeof cb[fn] == 'function') return cb[fn](kc);
return true;
}

function init(){
initted = true;
document.onkeydown = function(evt){ return onKey(evt, down) }
document.onkeyup = function(evt){ return onKey(evt, up) }
}
}

....I'm sure I'm not the first person who's thought of this, so I
assume there is some reason that it's wrong / bad / suboptimal or
you'd probably see it all over the place, but it sure looks a lot
neater. Maybe using new on an anonymous function with no argument list
is alright?

As an extension of that, what about calling throwaway closures with
new, maybe something like this?

delete new function { /* do stuff here; 'this' is a temp object. */ }

Thoughts?
From: nick on

> delete new function { /* do stuff here; 'this' is a temp object. */ }

should be

delete new function(){ /* do stuff here... */ }
From: "Michael Haufe ("TNO")" on
On Mar 30, 9:41 pm, nick <nick...(a)fastmail.fm> wrote:

> delete new function { /* do stuff here; 'this' is a temp object. */ }

delete should only be used for property removal. This is an error in
ES5.
From: nick on
On Mar 31, 1:01 am, "Michael Haufe (\"TNO\")"
<t...(a)thenewobjective.com> wrote:
> On Mar 30, 9:41 pm, nick <nick...(a)fastmail.fm> wrote:
>
> > delete new function { /* do stuff here; 'this' is a temp object. */ }
>
> delete should only be used for property removal. This is an error in
> ES5.

Fair enough, that's what the docs at MozDev indicate too.

I just discovered a weird side effect that I don't really understand
yet... I wanted a function to be able to chain itself to avoid passing
an array as the argument, so I did this:

this.register = function (key, onPress, onRelease) {
if (!initted) init();
if (!onPress && !onRelease) unregister(key);
callbacks[toCharCode(key)] = [onPress, onRelease];
// alert(this);
return this.register;
}

....and then tried this...

myApp.keys.register('x', function(){alert(1)})
('y', function(){alert(2)})
('z', function(){alert(3)})

.... X and Y got registered, Z did not. The first two times around,
'this' was myApp.keys, but after that 'this' goes back to window /
global (tested FF / V8). Can anyone shed some light on why that
happens? Anyway, the obvious fix is to avoid 'this' inside of
functions, but I'd still like to understand why the change happens.

Anyway, here's what I ended up with...

window.myApp = window.myApp || {};
myApp.keys = myApp.keys || new function(){

const me = this, DOWN = 0, UP = 1;
var initted = false, callbacks = {};

// public methods

this.register = function register (key, onPress, onRelease) {
if (!initted) init();
if (!onPress && !onRelease) unregister(key);
callbacks[toCharCode(key)] = [onPress, onRelease];
// alert(this);
return register;
}

this.unregister = function unregister (key) {
delete callbacks[key];
return unregister;
}

this.list = function (key) {
return key ? callbacks[key] : callbacks;
}

this.clear = function () { callbacks = {}; return me }

// private methods

function init(){
initted = true;
document.onkeydown = function(evt){ return on(evt, DOWN) }
document.onkeyup = function(evt){ return on(evt, UP) }
}

function on(evt, fn) {
evt = evt || window.event; //IE reports window.event
var cb = callbacks[evt.chrCode || evt.keyCode];
if (cb && typeof cb[fn] == 'function') return cb[fn](evt);
return true;
}

function toCharCode(v){
return v === +v ? v : (v+'_').toUpperCase().charCodeAt(0);
}

}
From: Richard Cornford on
On Mar 31, 3:41 am, nick wrote:
> So, I was using the good old module pattern, and I had
> some generic key handling code like this...
>
> window.myApp = {}; // so this example will run
> myApp.keys = (function(){
>
> const down = 0, up = 1, callbacks = {};
^^^^^
So this is JavaScript(tm) only, not a (cross or multi) browser script?

> var initted = false;
>
> // public methods
> return {
> register : function (key, onPress, onRelease) {
> if (!initted) init();
> key = key === +key ? key :
> (key+'_').toUpperCase().charCodeAt(0);
>
> callbacks[key] = [onPress, onRelease];
> },
> unregister : function (key) { delete callbacks[key] }
> }
>
> // private methods
> // ...

I always think that code in a function body after a - return -
statement is needlessly obscure/confusing. Personally, I prefer
function code to be structured such that it reflects how it will be
handled; to reflect the two phase - variable instantiation then code
execution handling, so with the variable and inner function
declarations at the top.

> })();
>
> ... and something hit me. You see that anonymous function
> calling itself (closure) all the time. Wouldn't it look a
> lot cleaner like this...

Isn't "cleaner" a judgment based on appearance?

> myApp.keys = new function(){
>
> const down = 0, up = 1, callbacks = {};
>
> var initted = false;
>
> // public methods
>
> this.register = function (key, onPress, onRelease) {
> if (!initted) init();
> key = key === +key ? key :
> (key+'_').toUpperCase().charCodeAt(0);
> callbacks[key] = [onPress, onRelease];
> }
>
> this.unregister = function (key) { delete callbacks[key] }
>
> // private methods
>
> function onKey(evt, fn) {
> evt = evt || window.event; //IE reports window.event
> var kc = evt.chrCode || evt.keyCode, cb = callbacks[kc];
> if (cb && typeof cb[fn] == 'function') return cb[fn](kc);
> return true;
> }
>
> function init(){
> initted = true;
> document.onkeydown = function(evt){ return onKey(evt, down) }
> document.onkeyup = function(evt){ return onKey(evt, up) }
> }
>
> }

In that case you are using the object created as a consequence of the
use of the new operator. However, the structure that is the function
expression immediately called is used for more purposes than creating
single standard javascript objects with specified methods and
properties. For any other purpose the use of the - new - operator
would be inappropriate; the created object would not be employed and
the resulting code would become more obscure than necessary as any
reader would then wonder why the object was being created, what
purpose it served. The extra examination of the code necessary to
determine that the created object was useless, unnecessary and
superfluous would suggest that it would be better not to use a
construct that created one. And so the - (function(){ ... })(); -
structure remains, must (eventually) be understood by any javascript
developer, and so should not inhibit the understanding of code where
it is used to create a single instance of a standard javascript
object.

> ...I'm sure I'm not the first person who's thought of this,

No, it has even been (inappropriately) employed in one or two general
purpose javascript libraries.

> so I assume there is some reason that it's wrong / bad /
> suboptimal or you'd probably see it all over the place,

The history of browser scripting has never shown any relationship
between the commonly observed and any notions of good/bad, right/
wrong, optimal/inefficient, etc./etc. The vast majority of browser
script authors have a negligible understanding of what they are doing
and so the vast majority of the scripts produced are uninformed in
design and/or execution.

> but it sure looks a lot neater.

I don't see much in it, though I would prefer to see the - new -
operator only used in conjunction with references to functions that
are designed as constructors for (possibly) multiple instances of a
type of object.

> Maybe using new on an anonymous function with no argument list
> is alright?

It is correct javascript syntax.

> As an extension of that, what about calling throwaway closures
> with new, maybe something like this?
>
> delete new function { /* do stuff here; 'this' is a temp object. */ }
^^^
()?
>
> Thoughts?

Apart from the previously commented upon, useless and so superfluous,
- delete - operation (why not - void -, or nothing at all as - new
function(){ ... }; - is a perfectly fine ExpressionStatement on its
own?), what does "'this' as temp object" mean? And when there is no
use for the object created by the - new - operator do you use a
different structure, or just create and throw it away unused?

Richard.