I am relatively new to JavaScript, though not to programming, and
I'm having trouble finding the idiomatic JS solution to the following
problem.
I have a table with (say) fields f1, f2, f3. I do a database
query and what I wind up with is a structure Q of arrays:
Q.f1[n] is field f1 in row n,
Q.f1.length == Q.f2.length == Q.f3.length is the record count of the query.
(This representation is of course backwards, but that's what ColdFusion's
CFWDDX facility produces, so I'm stuck with it.)
Now I have an array of row-numbers, which is supposed to represent a
subset of the query I just made:
A = [3, 6, 7] would represent rows 3, 6, 7 of query Q.
What I want to do is to sort A on a _specific_field _ of the query.
That is, produce a function compare(m, n) so that A.sort(compare)
sorts A in order corresponding to a specific field of Q.
Right now, I have separate handwritten comparators for each field:
function compare_f1(m, n) {
return Q.f1[m] < Q.f1[n] ? -1 :
Q.f1[m] > Q.f1[n] ? 1 : 0;
}
Obviously this is stupid.
(1)
I tried the approach that would be obvious in Lisp:
function comparator(fiel dname, invert) {
function compare(m, n) {
var comparison = Q[fieldname][m] < Q[fieldname][n] ? -1 :
Q[fieldname][m] > Q[fieldname][n] ? 1 : 0;
return invert ? -comparison : comparison;
}
return compare;
}
I expected this _not_ to work since I had thought JavaScript was
dynamically scoped. That is, I had thought something like
var c2 = comparator('f2' , false);
var fieldname = 'f3';
A.sort(c2);
would sort A using the wrong order, according to f3 (since 'compare'
isn't closed over the lexical environment containing 'fieldname').
But it seems to work correctly. Why does it work -- or does it work
only superficially?
(2)
Another approach I thought of, but which I was unable to get to work,
is to try making a 'functor' (function object) as in C++:
function compare(m, n) {
var fieldname = this.fieldname;
var invert = this.invert;
var comparison = Q[fieldname][m] < Q[fieldname][n] ? -1 :
Q[fieldname][m] > Q[fieldname][n] ? 1 : 0;
return invert ? -comparison : comparison;
}
function Comparator(fiel dname, invert) {
this.fieldname = fieldname;
this.invert = invert;
this.compare = compare;
}
Unfortunately if you then do
var c2 = new Comparator('f2' , false);
A.sort(c2.compa re);
the result is an error because the reference to 'this.fieldname '
inside the body of 'compare' does not treat 'this' as 'c2' as I
intended it to; 'this.fieldname ' is undefined.
An alternative strategy would be to try to make the Comparator
itself applicable, i.e., instead of
this.compare = compare;
put
Comparator.prot otype = compare;
and then try
A.sort(c2);
This doesn't work; c2 can't be applied.
So, does (1) work, and why or why not?
And is there a way to make something like (2) work?
Thanks for your time.
--
Chris Jeris
cj****@oinvzer. net
Apply (1 6 2 4)(3 7) to domainname to reply.