Share

YUI Library

Tracker: Feature Requests

5 [#2376988] "foo[foo.length] = bar" considered harmful? - ID: 1884328
Last Update: Comment added ( gpuckett )

This is a long comment on a programming pattern used in YUI, so don't read
it last thing on a Friday afternoon ;)

In a lot of places, YUI libraries push values on to the end of a list by
doing:

myArray[myArray.length] = something

I assume this is a speed issue rather than a compatibility problem, because
push() is also used sometimes.

Although this pattern is used in many places, it's common to see it in
string concatenation operations (because of IE's famous speed issues).
Here's a completely random example, taken from calendar.js:

html[html.length] = "<thead>";
html[html.length] = "<tr>";
html[html.length] = '<th colspan="' + colSpan + '" class="' +
this.Style.CSS_HEADER_TEXT + '">';
html[html.length] = '<div class="' + this.Style.CSS_HEADER + '">';

Because foo[foo.length] takes a while to type, it encourages the programmer
to split strings based on elegance rather than efficiency. This causes two
problems:

1) Strings combined with "+" that would be better written as two seperate
push operations. For example, the third line above combines several
strings with "+" because they're all logically part of a single tag, even
though this causes speed problems in IE.

2) Strings written as separate push operations that would be better
combined with "+". The YUI compressor will combine two literal strings
separated by "+" into one long string, so the first two lines in the above
example should be combined that way.

The net effect of this is to decrease efficiency and increase code size.
There are several possible solutions, which I'll spend the rest of this
post discussing. Perhaps unsurprisingly, I will leave my favourite until
last.

_ Add it to the style guide _

I assume that the use of foo[foo.length] is mandated in some style guide.
Wherever this rule is written down, it could be amended with a line like
"avoid the temptation to concatenate things with '+'".

While this is the simplest solution, its chances of working are slim:
programmers use the '+' because it comes naturally and makes their lives
easier. A comment like this would just remind them that the shortcut
exists.

_ Give up on foo[foo.length] and use push() _

This is a more practical solution, albeit one that loses the benefits of
foo[foo.length]. Ideally, the above example could be rewritten as:

html.push("<thead>" +
"<tr>" +
'<th colspan="', colSpan, '" class="', this.Style.CSS_HEADER_TEXT, '">'
+
'<div class="', this.Style.CSS_HEADER, '">'
);

This allows the YUI compressor to do its job, but puts a small burden on
the programmer to remember when to use '+' and when to use ','.

_ Create a new function: Array.yui_push() _

In the above example, the YUI compressor can't automatically determine
whether to combine literal strings because sometimes it's necessary for
push()ed strings not to be combined. That problem can be solved by
creating a yui_push() function:

Array.prototype.yui_push = Array.prototype.push;

The above example could then be rewritten as:

html.yui_push("<thead>",
"<tr>",
'<th colspan="', colSpan, '" class="', this.Style.CSS_HEADER_TEXT,
'">',
'<div class="', this.Style.CSS_HEADER, '">'
);

In uncompressed code, this would run perfectly well, although slightly
slower than before. The YUI compressor could transform this into either:

html.push('<thead><tr><th colspan="',colSpan,'"
class="',this.Style.CSS_HEADER_TEXT,'"><div
class="',this.Style.CSS_HEADER,'">');

Or:

html[html.length]='<thead><tr><th colspan="';
html[html.length]=colSpan;
html[html.length]='" class="';
html[html.length]=this.Style.CSS_HEADER_TEXT;
html[html.length]='"><div class="';
html[html.length]=this.Style.CSS_HEADER;
html[html.length]='">';

Depending on whether the user requested compact or fast handling of
Array.yui_push().

- Andrew


Andrew Sayers ( andrew_sayers ) - 2008-02-01 11:08

5

Closed

None

george puckett

None

None

Public


Comments ( 2 )

Date: 2009-01-23 00:46
Sender: gpuckettProject Admin

The YUI project has been migrated from Source Forge to YUILibrary.com.
This ticket has been moved to the tracker on YUILibrary.com that
corresponds to the project it was filed against (YUI2, YUI3, Compressor,
etc.). All bugs not yet closed on Source Forge have been transferred with
their current state intact. The Source Forge version of all bugs are
being marked as closed to avoid confusion. You can track the
status/progress of this ticket on http://yuilibrary.com/ using the same
ticket ID as it held in Source Forge.



Date: 2008-02-28 16:37
Sender: miragliaProject Admin


Andrew,

Thanks for the thoughtful comment here. Am forwarding to the queue of
Matt Sweeney who is looking closely at JS style issues as we rennovate
YUI's underlying architecture.

-Eric


Attached File

No Files Currently Attached

Changes ( 7 )

Field Old Value Date By
status_id Open 2009-01-23 00:46 gpuckett
assigned_to msweeney 2009-01-23 00:46 gpuckett
allow_comments 1 2009-01-23 00:46 gpuckett
close_date - 2009-01-23 00:46 gpuckett
summary "foo[foo.length] = bar" considered harmful? 2008-11-21 21:53 gpuckett
assigned_to miraglia 2008-02-28 16:37 miraglia
assigned_to nobody 2008-02-01 21:08 gpuckett