concatenating variable names

D

David Williams

Does anyone know how to generate a array name on the fly?

Like
for(i=0;i<10;i++){_
var a+i=new Array(40)
}
where I have a new array named a1, a2, a3, etc?

var a+i is not working for me
var (a+i) is not working for me either
Thanks
David

--
 
T

Thomas 'PointedEars' Lahn

David said:
Does anyone know how to generate a array name on the fly?

You really don't want that, trust me.
Like
for(i=0;i<10;i++){_
^
Always declare your identifiers, else the scope of them extends to outer
execution contexts and may also cause a runtime error in certain
environments (most notably, MSHTML).

Use spaces to make your code easier legible, both between tokens and as
indentation character.

The `_' must be a typo. (This isn't VBScript, where `_' serves as a line
continuation token.)
var a+i=new Array(40)

Never call the Array constructor/factory with a single numeric argument N.
The outcome is either an array with N elements with the `undefined' value
(which eat up memory to no purpose), or an array with one element with
value N. ECMAScript arrays are automatically resized as elements are
added, there is seldom a need to initialize them like that.
}
where I have a new array named a1, a2, a3, etc?

You want an array of arrays instead, see
<(note the date)

var a = [];

for (var i = 10; i--;)
{
a = [];
}
var a+i is not working for me
var (a+i) is not working for me either

Of course, it's a syntax error. <http://jibbering.com/faq/#posting>


PointedEars
 
R

RoLo

Does anyone know how to generate a array name on the fly?
you mean variable name on the fly?
Like
for(i=0;i<10;i++){_
var a+i=new Array(40)}

ugly I bet theres a better way to make whatever your doing...

But since you ask, you could do it with eval.
Maybe:

for(i=0;i<10;i++)
eval('var a'+i+'=new Array(40)');
 
T

Thomas 'PointedEars' Lahn

Conrad said:
Never call the Array constructor/factory with a single numeric
argument N. The outcome is either an array with N elements with the
`undefined' value (which eat up memory to no purpose),

Why should
var x = new Array(10000);
eat any more memory than
var x = [];
?

It shouldn't; my bad. The first variant is specified to only set the
`length' property.
As long as the argument is an integer in the supported range, it has to
be used to set the length property, not to add any elements. Are there
any implementations that got this wrong?

Yes.


PoitedEars
 
S

Stevo

kangax said:
Thomas said:
^
Always declare your identifiers, else the scope of them extends to outer
execution contexts and may also cause a runtime error in certain
environments (most notably, MSHTML).

Too bad this is not stressed more often. I was recently surprised to
find gooogle's (afaik, widely used) `excanvas.js` "exporting" global
references in exactly such way - by assigning to undeclared variables
[1]. There's even this innocent comment next to it - "set up externs" :)

[1]
http://excanvas.svn.sourceforge.net/viewvc/excanvas/excanvas.js?revision=44&view=markup#l_868

There's a big difference between what the OP did here (using i without
declaring it and therefore overwriting any global variable called i),
and what that google canvas code is doing. You even told us that they
know they're doing it deliberately by using the comment "set up
externs". That indicates they're intentionally taking advantage of this
behavior to create some global variables. Here are two lines from that
code, note the prefix G_ which gives another clue.

// set up externs
G_vmlCanvasManager = G_vmlCanvasManager_;

Personally, I would have declared that with window.G_vmlCanvasManager
and I don't split the word setup into two words either.
 
T

Thomas 'PointedEars' Lahn

kangax said:
I use explicitly declared `global` instead of `window`. I guess it's a
matter of preference : )

It's a matter of reliability. `window' is supposed to refer to a host
object. As for `global', I am currently using `_global' instead in the
attempt to avoid overwriting an existing `global' property of the Global
Object. It might also be a good idea not to declare `global' because of
upcoming editions of ECMAScript being currently worked on which seem to
introduce that global property name with different behavior.


PointedEars
 
D

David Williams

Hello all, I thought I posted a followup yesterday
but I found an example on the web that helped

Thanks to all who made comments, especially the eval recommendation

Here is what worked for me

var a="a"
var b="b"
eval(a+b+"=new Array(40)");
gave me the new ab variable, which is an array

David


David Williams said:
Does anyone know how to generate a array name on the fly?
Like
for(i=0;i<10;i++){_
var a+i=new Array(40)
}
where I have a new array named a1, a2, a3, etc?
 
T

Thomas 'PointedEars' Lahn

David said:
Here is what worked for me

Try it in Internet Explorer in a HTML document with an element that has name
or ID "ab" (or whatever the real name is). You'll be surprised.
var a="a"
var b="b"
eval(a+b+"=new Array(40)");
gave me the new ab variable, which is an array

No, it gave you an error-prone assignment to a property of an object in the
scope chain, that refers to an Array object.


PointedEars
 
T

Thomas 'PointedEars' Lahn

Conrad said:
Okay. Do you know which ones?

Not precisely, I encountered it quite some time ago. I presume it is
JavaScript 1.2 or earlier, or JavaScript 1.3 and later with
language="JavaScript1.2" which are not fully conforming implementations of
ECMAScript; there should be at least one discussion about it in the Google
archives of this newsgroup or of de.comp.lang.javascript. I'll tell you if
I find it first or have a test case.

Nevertheless, I think the possibility of such a bug should be considered.


PointedEars
 
T

Thomas 'PointedEars' Lahn

Thomas said:
Try it in Internet Explorer in a HTML document with an element that has
name or ID "ab" (or whatever the real name is). You'll be surprised.


No, it gave you an error-prone assignment to a property of an object in
the scope chain, that refers to an Array object.

To be a bit more constructive, you could use

eval("var " + a + b + " = new Array(40);");

instead for a local variable. But again, I strongly advise against it; use
property accessors instead, e.g. for a rather safe global property:

var _global = this;

function foo(a, b)
{
_global[a + b] = new Array(40);
}

foo("a", "b");

Or use a user-defined object instead of the Global Object, which is even
safer (and less prone to side-effects).

See also:
| 6.1 When should I use eval?
<http://jibbering.com/faq/#eval>


PointedEars
 
D

David Williams

Thanks Thomas,
I did not know of such a danger in using eval.

I will try the property accessor way.


Thomas 'PointedEars' Lahn said:
Thomas 'PointedEars' Lahn wrote:
To be a bit more constructive, you could use
eval("var " + a + b + " = new Array(40);");
instead for a local variable. But again, I strongly advise against it; use
property accessors instead, e.g. for a rather safe global property:
var _global = this;
function foo(a, b)
{
_global[a + b] = new Array(40);
}
foo("a", "b");
 
D

dhtml

Conrad said:
Never call the Array constructor/factory with a single numeric
argument N. The outcome is either an array with N elements with the
`undefined' value (which eat up memory to no purpose),

Why should
var x = new Array(10000);
eat any more memory than
var x = [];
?
or an array with one element with value N.

As long as the argument is an integer in the supported range, it has to
be used to set the length property, not to add any elements. Are there
any implementations that got this wrong?

Firefox <= 2 would create elements with value undefined.

in Firefox 2,
'2' in new Array(10)

resulted true. Fixed in FF3.

Initializing an array's length can have a minor (maybe negligible)
performance improvement.

This is because an Array has a specialized [[Put]] method. It is as follows:

| 1. Call the [[CanPut]] method of A with name P.
| 2. If Result(1) is false, return.
| 3. If A doesn't have a property with name P, go to step 7.
| 4. If P is "length", go to step 12.
| 5. Set the value of property P of A to V.
| 6. Go to step 8.
| 7. Create a property with name P, set its value to V and give it empty
| attributes.
| 8. If P is not an array index, return.
| 9. If ToUint32(P) is less than the value of the length property of A,
| then return.
| 10. Change (or set) the value of the length property of A to
| ToUint32(P)+ 1.
| 11. Return.

In step 9, there is a chance at early return, which would result in
skipping step 10 (and 11). This will happen when "ToUint32(P) is less
than the value of the length property of A".

This can be applied when creating a new Array that is the result of a
merge or union of two or more collections or is a subset of a collection
(such as a filtering function like a custom getElementsByClassName).

When the resulting array is populated in a loop, set the array's length,
populate the array in the loop while maintaining the index of the last
added element, then after the loop, trim the array.

var max_possible_length = 1000000,
a = new Array(max_possible_length),
condition;

for(var i = 0, c = 0; i < max_possible_length; i++) {
condition = i % 7 === 0;
if(condition) {
a[c] = i;
c++;
}
}

a.length = c;

The loop keeps track of a counter |c|. This is the number of items added
to the array. After the loop is finished, the array is trimmed by
setting its length to |c|.

Though the performance improvement is almost negligible.

Garrett
 
M

Michael Wojcik

Stevo said:
// set up externs
G_vmlCanvasManager = G_vmlCanvasManager_;

Personally, I would have declared that with window.G_vmlCanvasManager
and I don't split the word setup into two words either.

There's a relatively common convention in English for verb-preposition
portmanteaus like "setup" / "set up": concatenate when used as a noun,
but leave separate when used as a verb.

Consider "We will sing along at a singalong", for example.

This has various advantages. It permits the less-awkward placement of
a direct object immediately after the verb ("set externs up"). In
spoken English, there's often a slight pause between the verb and the
preposition, and equal stress on both ("I set' up' the server'"),
whereas in the noun form there's typically no pause and stress only on
the verb-part ("check the server's set'up"). For verbs that inflect
for tense, it lets other tenses be formed correctly ("we sang along at
the singalong", or "I backed the server up"); this doesn't apply in
the particular case of "setup" (as "set" doesn't inflect for tense),
but there's no reason to make it a special case.
 
T

Trevor Lawrence

you mean variable name on the fly?


ugly I bet theres a better way to make whatever your doing...

But since you ask, you could do it with eval.
Maybe:

for(i=0;i<10;i++)
eval('var a'+i+'=new Array(40)');


Bingo,

I have done just that myself, but I thought that it would be dangerous to
suggest that here, especially as JSLint says "eval is evil"

I used it like this, where qsobj(0) extracts the contents of the string in a
URL after '?'
For example, if the URL is gallery.html?ssarray=no1,no2,no3
qsobj(0) is the string 'no1,no2,no3'

var ssarray = qsobj(0).split(",");
var ssarrlen = ssarray.length;

var Picturesx = [];
var Captionsx = [];
for (var i = 1; i <= ssarrlen; i++) {
eval('Pictures' + i + '= [];'
+ 'Captions' + i + '= [];'
+ 'Picturesx.push(Pictures' + i + ');'
+ 'Captionsx.push(Captions' + i + ');' );
}

The result is that the array Picturesx contains the arrays Pictures1,
Pictures2, Pictures3, etc. up to as many separate names as are present in
the string 'no1,no2,no3' (in this case, 3)

Ditto for Captionsx

Is there a better (or cleaner) way to do this?

While I am here, what are the merits or otherwise of using array_name= [] ;
vs. array_name = new Array(); ?

JSLint say that the former is preferable, but isn't the latter clearer as to
its intent?
 
J

Jorge

While I am here, what are the merits or otherwise of using array_name= [] ;
vs.  array_name = new Array(); ?

JSLint say that the former is preferable, but isn't the latter clearer asto
its intent?

Not for me. array= []; (clearly) assigns an empty array to array...
 
L

Lasse Reichstein Nielsen

Trevor Lawrence said:
Bingo,

I have done just that myself, but I thought that it would be dangerous to
suggest that here, especially as JSLint says "eval is evil"

And it's right.

I find it hard to see a reason to create variables dynamically at runtime.
After all, variables are just names that have to match between declaration
and use. If you declare the variables dynamically, you have to create
the uses dynamically too. The whole idea of a variable goes out the
window.
If the variables are only differ by a number, it seems like a very
convoluted way of implementing an array.

I used it like this, where qsobj(0) extracts the contents of the string in a
URL after '?'
For example, if the URL is gallery.html?ssarray=no1,no2,no3
qsobj(0) is the string 'no1,no2,no3'

var ssarray = qsobj(0).split(",");
var ssarrlen = ssarray.length;

var Picturesx = [];
var Captionsx = [];
for (var i = 1; i <= ssarrlen; i++) {
eval('Pictures' + i + '= [];'
+ 'Captions' + i + '= [];'
+ 'Picturesx.push(Pictures' + i + ');'
+ 'Captionsx.push(Captions' + i + ');' );
}

The result is that the array Picturesx contains the arrays Pictures1,
Pictures2, Pictures3, etc. up to as many separate names as are present in
the string 'no1,no2,no3' (in this case, 3)

Ditto for Captionsx

Where do you use Pictures1? Why don't you just use Picturesx[1] instead?
If you don't use it, why do you create the variable at all?
(And remember to use "var" to declare variables!)
Is there a better (or cleaner) way to do this?

var Picturesx = [];
var Captionsx = [];
for (var i = ; i < ssarrlen; i++) {
Picturesx = [];
Captionsx = [];
}

/L
 
T

Trevor Lawrence

Lasse Reichstein Nielsen said:
Trevor Lawrence said:
Bingo,

I have done just that myself, but I thought that it would be dangerous to
suggest that here, especially as JSLint says "eval is evil"

And it's right.

I find it hard to see a reason to create variables dynamically at runtime.
After all, variables are just names that have to match between declaration
and use. If you declare the variables dynamically, you have to create
the uses dynamically too. The whole idea of a variable goes out the
window.
If the variables are only differ by a number, it seems like a very
convoluted way of implementing an array.

I used it like this[snip]

The result is that the array Picturesx contains the arrays Pictures1,
Pictures2, Pictures3, etc. up to as many separate names as are present in
the string 'no1,no2,no3' (in this case, 3)

Ditto for Captionsx

Where do you use Pictures1? Why don't you just use Picturesx[1] instead?
If you don't use it, why do you create the variable at all?
(And remember to use "var" to declare variables!)

Thanks, I overlooked the "var"

Well, I set each of the arrays Pictures1, Pictures2, etc in other JS

A snippet of the code is:
function setPicNames (colln) {
switch(ssarray [colln]) {
case 'no1':
Picturesx[colln].push(

// Enter Slideshow picture filenames here
"nessie" ,
"michelle" ,
"al-tony" ,
"bi_plane"
) ;

In this case, colln has the value 0 and so Picturesx[colln] is Pictures1. I
need to set up Picturesx as an array of arrays, where each of the latter
(inner) arrays can have differing lengths. However, I have just checked and
nowhere do I refer to Pictures1, etc.
Is there a better (or cleaner) way to do this?

var Picturesx = [];
var Captionsx = [];
for (var i = ; i < ssarrlen; i++) {
Picturesx = [];
Captionsx = [];
}


Ahah. It is so obvious when I see it .

Thank you your help. I can now avoid the evil eval
 
G

Garrett Smith

Conrad said:
I could not reproduce this in Firefox 2 (v2.0.0.20).
Perhaps the bug was fixed in an earlier version.
Do you by any chance know the bug id on bugzilla.mozilla.org?
https://bugzilla.mozilla.org/show_bug.cgi?id=260106

The bug only occurred with array literals, not the constructor.

Example:
var x = [1,,2];
x.length = 10;
x.hasOwnProperty("1")
typeof x[1]

true.

I'm getting the same result in FF3 now.

Back to the original topic, we do not have a browser that would add
elements to the array with new Array(10).

Garrett
 

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

Forum statistics

Threads
474,116
Messages
2,570,699
Members
47,274
Latest member
SeleneHgw8

Latest Threads

Top