A question of style, or something more....

T

teddysnips

A newbie writes:

Is there any reason to choose one over the other of the following two
ways to write a Javascript function? The function is called when a
drop-down list is changed, and navigates to a different page depending
on the value chosen:

<script language="JavaScript">
<!--
// Version 1.0

function MoveToPage(el)
{//v1.0
if(el.options[el.selectedIndex].text=='value 1')
{
document.getElementById('form_eng').action =
'report1.asp';
}
else if(el.options[el.selectedIndex].text=='value 2')
{
document.getElementById('form_eng').action =
'report2.asp';
}
else if(el.options[el.selectedIndex].text=='value 3')
{
document.getElementById('form_eng').action =
'report3.asp';
}
document.getElementById('form_eng').submit();
}
-->
</script>


================

<script language="JavaScript">
<!--
//Version 1.1
function MoveToPage(el)
{//v1.1
var form;
form = document.getElementById('form_eng')
var
report=el.options[el.selectedIndex].text;
if(report=='value 1')
{
form.action = 'report1.asp';
}
else if(report=='value 2')
{
form.action = 'report2.asp';
}
else if(report=='value 3')
{
form.action = 'report3.asp';
}
form.submit();
}
-->
</script>
 
B

Bruno Desthuilliers

(e-mail address removed) a écrit :
A newbie writes:

Is there any reason to choose one over the other of the following two
ways to write a Javascript function? (snip)

function MoveToPage(el)
{//v1.0
if(el.options[el.selectedIndex].text=='value 1')
{
document.getElementById('form_eng').action =
'report1.asp';
}
else if(el.options[el.selectedIndex].text=='value 2')
{
document.getElementById('form_eng').action =
'report2.asp';
} (snip)


function MoveToPage(el)
{//v1.1
var form;
form = document.getElementById('form_eng')
var
report=el.options[el.selectedIndex].text;
if(report=='value 1')
{
form.action = 'report1.asp';
}
else if(report=='value 2')
{
form.action = 'report2.asp';
}
(snip)

The second version is more readable, and will waste less time looking up
the same attribute. FWIW, using a hash-table would probably be better:

<script type="text/javascript">

var ACTIONS_TABLE = {
value_1: 'report1.asp',
value_2: 'report2.asp',
value_3: 'report3.asp'
}

function MoveToPage(el) {
//v1.2
var form = document.getElementById('form_eng');
if (! form) {
return;
}
var report=el.options[el.selectedIndex].text;
try {
form.action = ACTIONS_TABLE[report];
}
catch(e) {
// XXX : add proper error handling here
alert("no action for '" + report + "'");
return;
}
form.submit();
}
</script>

My 2 cents...
 
T

The Natural Philosopher

A newbie writes:

Is there any reason to choose one over the other of the following two
ways to write a Javascript function? The function is called when a
drop-down list is changed, and navigates to a different page depending
on the value chosen:

Well. It all depends on how good the javascript interpreter is.

A good optimising C compiler looking at all that would stash what you
have put in 'form' and 'report' in temporary variables anyway..so under
an optimising compiler the actual code would be identical.

A poor..very poor ..interpreter might use more cycles to execute the
first..so I'd always write it the second way, because I grew up with
assemblers, which don't do anything you don tell them to, and poor
compilers, which didn't even do what you told them to half the time.

If you really care. put the two samples inside a loop and iterate
through a few thousand times and time them.

<script language="JavaScript">
<!--
// Version 1.0

function MoveToPage(el)
{//v1.0
if(el.options[el.selectedIndex].text=='value 1')
{
document.getElementById('form_eng').action =
'report1.asp';
}
else if(el.options[el.selectedIndex].text=='value 2')
{
document.getElementById('form_eng').action =
'report2.asp';
}
else if(el.options[el.selectedIndex].text=='value 3')
{
document.getElementById('form_eng').action =
'report3.asp';
}
document.getElementById('form_eng').submit();
}
-->
</script>


================

<script language="JavaScript">
<!--
//Version 1.1
function MoveToPage(el)
{//v1.1
var form;
form = document.getElementById('form_eng')
var
report=el.options[el.selectedIndex].text;
if(report=='value 1')
{
form.action = 'report1.asp';
}
else if(report=='value 2')
{
form.action = 'report2.asp';
}
else if(report=='value 3')
{
form.action = 'report3.asp';
}
form.submit();
}
-->
</script>
 
T

teddysnips

[email protected] a écrit :> A newbie said:
Is there any reason to choose one over the other of the following two
ways to write a Javascript function?
(snip)





function MoveToPage(el)
{//v1.0
if(el.options[el.selectedIndex].text=='value 1')
{
document.getElementById('form_eng').action =
'report1.asp';
}
else if(el.options[el.selectedIndex].text=='value 2')
{
document.getElementById('form_eng').action =
'report2.asp';
} (snip)

function MoveToPage(el)
{//v1.1
var form;
form = document.getElementById('form_eng')
var
report=el.options[el.selectedIndex].text;
if(report=='value 1')
{
form.action = 'report1.asp';
}
else if(report=='value 2')
{
form.action = 'report2.asp';
}

(snip)

The second version is more readable, and will waste less time looking up
the same attribute. FWIW, using a hash-table would probably be better:

<script type="text/javascript">

var ACTIONS_TABLE = {
value_1: 'report1.asp',
value_2: 'report2.asp',
value_3: 'report3.asp'

}

function MoveToPage(el) {
//v1.2
var form = document.getElementById('form_eng');
if (! form) {
return;
}
var report=el.options[el.selectedIndex].text;
try {
form.action = ACTIONS_TABLE[report];
}
catch(e) {
// XXX : add proper error handling here
alert("no action for '" + report + "'");
return;
}
form.submit();}

</script>

My 2 cents...

Excellent - I'll give this a go!

Edward
 
T

teddysnips

Well. It all depends on how good the javascript interpreter is.

A good optimising C compiler looking at all that would stash what you
have put in 'form' and 'report' in temporary variables anyway..so under
an optimising compiler the actual code would be identical.

A poor..very poor ..interpreter might use more cycles to execute the
first..so I'd always write it the second way, because I grew up with
assemblers, which don't do anything you don tell them to, and poor
compilers, which didn't even do what you told them to half the time.

If you really care. put the two samples inside a loop and iterate
through a few thousand times and time them.

It's not that I care so much one way or t'other. Obviously, in a
piddling function like this, the number of extra cycles would be
negligible. I guess, from your response and Bruno's the second way is
preferable. Which I suppose I always thought it would be....

Thanks

Edward
 
J

Janwillem Borleffs

(e-mail address removed) schreef:
<script language="JavaScript">
<!--
//Version 1.1
function MoveToPage(el)
{//v1.1
var form;
form = document.getElementById('form_eng')
var
report=el.options[el.selectedIndex].text;
if(report=='value 1')
{
form.action = 'report1.asp';
}
else if(report=='value 2')
{
form.action = 'report2.asp';
}
else if(report=='value 3')
{
form.action = 'report3.asp';
}
form.submit();
}
-->
</script>

I would prefer this style because of readability and that the property
doesn't need to be retrieved for each condition.

BTW, if the option is list is indeed 'value 1'...'value 3', you could
also write:

function MoveToPage(el) {
var form = document.getElementById('form_eng');
var page = 'report' + (el.selectedIndex + 1) + '.asp';
form.action = page;
form.submit();
}


JW
 
B

Bruno Desthuilliers

(e-mail address removed) a écrit :
(snip)
It's not that I care so much one way or t'other. Obviously, in a
piddling function like this, the number of extra cycles would be
negligible. I guess, from your response and Bruno's the second way is
preferable. Which I suppose I always thought it would be....

Well... It's not only a matter of extra cycles. The first and main
reason to prefer the second option is (IMHO) readabilty and
maintainability.
 
H

Henry

Well. It all depends on how good the javascript interpreter
is.

A good optimising C compiler looking at all that would stash what
you have put in 'form' and 'report' in temporary variables anyway.
.so under an optimising compiler the actual code would be identical.

A poor..very poor ..interpreter might use more cycles to execute
the first..so I'd always write it the second way, because I grew
up with assemblers, which don't do anything you don tell them to,
and poor compilers, which didn't even do what you told them to
half the time.

Remember that a C complier only builds an (individual) executable out
of source code once, and then the executable is (potentially) executed
directly many, many times. In this process it doesn't matter how long
the compilation process takes (within reason) so to opportunity to
examine the source code to identify the opportunities for optimization
are unlimited.

Javascript is delivered to its execution environment as source code
text and parsed/complied to something that can be executed prior to
each execution. This means that the time taken compiling will directly
impact on the user's perception of performance. And the number and
nature of optimisations that could be applied will directly impact on
the time taken to compile the code and so on the user's perception of
the performance of the result.

So an important criteria for a "good" javascript complier is that it
be a quick javascript complier.

The dynamic nature of javascript heavily impacts on what would be
required in order to apply optimisations. for example, when you say
that a good "good" compiler would "what you have put in 'form' and
'report' in temporary variables" you are implicitly suggesting that
all executions of - document.getElementById('form_eng') - (for
example) will result in the same code being executed and the same
value being returned. In javascript neither of those things are
necessarily true. The - getElementById - method of the document may
have been replaced with another function, and calls to that new
function may themselves re-replace the document's - getElementsById -
method. And those replacement method may return anything. It is also
the case that script code is imported in separate script elements, and
at different times during the loading of a page.

So for your "good" compiler to know that it was safe to be replacing
the coded action with an optimised alternative it has to examine all
of the javascript in the execution environment in order to be certain
that no actions could happen that would invalidate the optimizations
applied. Which means that for some optimizations it cannot act while
compiling the first script element's contents until it has access to
the code in the last script element (the existence of which it cannot
know about until the HTML parser has seen that element.

Given the need for a javascript compiler to be quick it is unrealistic
to expect it to be applying optimisations that require an examination
of all of the code being loaded into a page, or optimisations that
require a detailed examination of the permutations of possibilities
inherent in the code being loaded.

If you really care. put the two samples inside a loop and iterate
through a few thousand times and time them.

Or just write it the way that would run quickest if no optimisations
where applied (as in this case there is no negative impact on the
readability of the result) and let any quick and easy optimisations
that may be applied in its compilation be a bonus.
 
T

The Natural Philosopher

It's not that I care so much one way or t'other. Obviously, in a
piddling function like this, the number of extra cycles would be
negligible. I guess, from your response and Bruno's the second way is
preferable. Which I suppose I always thought it would be....

In the absence of performance tests, you have to assess it on other grounds.

Which is more understandable? more readable? takes less typing?

In my case the latter tends to dominate.

Others who do cut-and-paste these days, can touch type, and didn't grow
up with 'vi', may differ ;-)
 
T

The Natural Philosopher

Henry said:
Remember that a C complier only builds an (individual) executable out
of source code once, and then the executable is (potentially) executed
directly many, many times. In this process it doesn't matter how long
the compilation process takes (within reason) so to opportunity to
examine the source code to identify the opportunities for optimization
are unlimited.

Javascript is delivered to its execution environment as source code
text and parsed/complied to something that can be executed prior to
each execution. This means that the time taken compiling will directly
impact on the user's perception of performance. And the number and
nature of optimisations that could be applied will directly impact on
the time taken to compile the code and so on the user's perception of
the performance of the result.

So an important criteria for a "good" javascript complier is that it
be a quick javascript complier.

The dynamic nature of javascript heavily impacts on what would be
required in order to apply optimisations. for example, when you say
that a good "good" compiler would "what you have put in 'form' and
'report' in temporary variables" you are implicitly suggesting that
all executions of - document.getElementById('form_eng') - (for
example) will result in the same code being executed and the same
value being returned. In javascript neither of those things are
necessarily true. The - getElementById - method of the document may
have been replaced with another function, and calls to that new
function may themselves re-replace the document's - getElementsById -
method. And those replacement method may return anything. It is also
the case that script code is imported in separate script elements, and
at different times during the loading of a page.

So for your "good" compiler to know that it was safe to be replacing
the coded action with an optimised alternative it has to examine all
of the javascript in the execution environment in order to be certain
that no actions could happen that would invalidate the optimizations
applied. Which means that for some optimizations it cannot act while
compiling the first script element's contents until it has access to
the code in the last script element (the existence of which it cannot
know about until the HTML parser has seen that element.

Given the need for a javascript compiler to be quick it is unrealistic
to expect it to be applying optimisations that require an examination
of all of the code being loaded into a page, or optimisations that
require a detailed examination of the permutations of possibilities
inherent in the code being loaded.



Or just write it the way that would run quickest if no optimisations
where applied (as in this case there is no negative impact on the
readability of the result) and let any quick and easy optimisations
that may be applied in its compilation be a bonus.
Good points.

I had wondered about how much 'look ahead' javsacript interpreters do..
 
T

The Natural Philosopher

[email protected] a écrit :> A newbie said:
Is there any reason to choose one over the other of the following two
ways to write a Javascript function? (snip)





function MoveToPage(el)
{//v1.0
if(el.options[el.selectedIndex].text=='value 1')
{
document.getElementById('form_eng').action =
'report1.asp';
}
else if(el.options[el.selectedIndex].text=='value 2')
{
document.getElementById('form_eng').action =
'report2.asp';
} (snip)

function MoveToPage(el)
{//v1.1
var form;
form = document.getElementById('form_eng')
var
report=el.options[el.selectedIndex].text;
if(report=='value 1')
{
form.action = 'report1.asp';
}
else if(report=='value 2')
{
form.action = 'report2.asp';
}
(snip)

The second version is more readable, and will waste less time looking up
the same attribute. FWIW, using a hash-table would probably be better:

<script type="text/javascript">

var ACTIONS_TABLE = {
value_1: 'report1.asp',
value_2: 'report2.asp',
value_3: 'report3.asp'

}

function MoveToPage(el) {
//v1.2
var form = document.getElementById('form_eng');
if (! form) {
return;
}
var report=el.options[el.selectedIndex].text;
try {
form.action = ACTIONS_TABLE[report];
}
catch(e) {
// XXX : add proper error handling here
alert("no action for '" + report + "'");
return;
}
form.submit();}

</script>

My 2 cents...

Excellent - I'll give this a go!

Edward
Mnn. Beware again how the interpreter handles such elegant LOOKING
constructs.

I spent two days trying to get an array of pointers to functions to work
using a primitive 8 bit C compiler ..I never did make it understand..but
halfway through I looked at how it was taking the values 0, 1, 2 and 3
and applying them to that table structure. It was horrible,

Take the value.
Convert to 16 bit.
do a *long multiplication* by two to get the actual offset of the 16 bit
address from the array base (when a left shift would have been
INFINITELY quicker on a machine that only HAD an 8x8 multiplier onboard)
Add that by a pretty crap routine to the array base..

(And then fall over in terms of doing the call to the CONTENTS of that
address. I got it to call the ADDRESS. But any extra asterisks confused
the compiler. I could have done it in two seconds and 5 lines in
assembler..)

I then tried a switch...case statement.

That was equally horrid as every element of the index got upped to a 16
bit index, before going into a giant if..then..elseif.. construct that
the compiler generated. BUT it worked.

Finally the penny dropped. I stopped trying to second guess the compiler
and wrote

callmyfunc(index)
{
char index; /*thereby stopping most of the 16 bit rot.*/
If (index ==(char)1) return function1();
if (index==(char)2) return function2();
...

}
and so on

Magically, it decided NOT to promote index to a 16 bit quantity in order
to do the comparison, which is PROBABLY a violation of the C
specification, but heck, who's counting at this point?

Whilst not as small as the call table I was trying to emulate it was
fast enough and small enough..heck we were into 8x16k *paged in* ROM
slots anyway at that point on a 64K memory mapped 6809..16K RAM and 32K
'base' ROM..

All this got forgotten when super optimising compilers came in.. I
remember once dumping te assembler output of a code fragment I was
having trouble with and being utterly AMAZED at how neat a job the
compiler made of it. Half of my local variables were in registers.. and
beautifully optimised too..temporary variables that I hadn't explicitly
created had been created for me..teh compiler had obviously trolled
through to find common stuff and decided 'no need to do that every time.
it hasn't changed, we'll stuff it in a register'

But as 'Henry' has pointed out, Javascript is interpreted..and maybe it
doesn't have time to optimise, in which case its about 7 steps backward
in to the dark days of writing optimal code again.

- take everything out of a loop, that can be..
- use global variables everywhere and reuse them to avoid unnecessary
memory allocation .. ;-)
- tell the code exactly HOW to do what you want, not just what you want
done..
- avoid complex constructions that will be hard to parse..
- work with the native sizes of objects all the time. Avod 64 bit stuff
on a 32 bit machine if you can.
and so on.
 

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
474,156
Messages
2,570,878
Members
47,404
Latest member
PerryRutt

Latest Threads

Top