Imagine i had: <div id names>142,140,150</names>
could i then (in Javascript) write a forloop which declares variable names, with these values appended ie
var list = document.getElementById('names').innerHTML.Split(',');
for(i=0; i<list.Length; i++){
var 'beginning' + list[i];
}
so i'd essentially want to create:
var beginning142
var beginning140
var beginning150
You can indeed:
window['beginning' + list[i]] = 'value';
Funny coincidence, I answered a very closely related question 10 seconds prior to this one, and then I used exactly this as an example. So a more elaborate explanation on why this works is available here.
You can do something like this:
for(var i = 0; i<100; i++)
{
eval("var beginning"+i);
}
For developers afraid from eval This is one of good articles talking about eval and how it is not an evil: http://www.nczonline.net/blog/2013/06/25/eval-isnt-evil-just-misunderstood/
I’m not saying you should go run out and start using eval()
everywhere. In fact, there are very few good use cases for running
eval() at all. There are definitely concerns with code clarity,
debugability, and certainly performance that should not be overlooked.
But you shouldn’t be afraid to use it when you have a case where
eval() makes sense. Try not using it first, but don’t let anyone scare
you into thinking your code is more fragile or less secure when eval()
is used appropriately.
I can't add comment to your question due to low reputation score - this is not answer but advice.
I think It would be better to create single array with your keys 142,140,150...
Why don't you define an object that has those values as an attribute on it.
For example:
var myVariable = function(id, value){
this.Id = id;
this.Value = value;
};
then you can just instantiate this object. I think it is less complicated and more readable in the end.
Related
My question is more a curiosity question on for-loop style.
While reading some old code by others, I encountered a style I haven't seen before.
var declaredEarlier = Array
for(var i=0, length=declaredEarlier.length; i < length; i++) {
//stuff
}
I had never seen declaring a length before use and since this is an old app, was this kind of style a C/C++/old Java carryover? or was this developer unique?
Is there any benefit for declaring length that way instead of doing what I normally do:
for(var i=0; i < declaredEarlier.length; i++) {
//stuff
}
If this has been asked before, I could not find it. And if it's not stackoverflow applicable, which forum would be better to ask?
There are two reasons you might grab the length up-front like that:
In case the length may change (remember, JavaScript arrays aren't really arrays* and their length is not fixed) and you want to use the original length to limit the loop, or
To avoid repeatedly looking up the length on the object, since you know it's not going to change
The first is obviously substantive; the second is style and/or micro-optimisation.
* Disclosure: That's a link to a post on my anemic little blog.
for the first style the value of declaredEarlier can change so you need to use it
like that length=declaredEarlier.length
but for the second style you already know the value you dont need to calculate it again
Is it possible to define multiple variables with a single jQuery chain?
var sectionTable = jQuery("#sectionsTable");
var sectionTableRows = sectionTable.find("tr");
var sectionTableColumns = sectionTableRows.find("td");
I don't know what the syntax would be if it is possible but if you took the 3 variables above how could you chain them and would it be considered good practice?
Many thanks
Chris
EDIT: Wow, thanks for all the comments. Sorry for being vague, what I was after was a better way (if one exists) of defining child variables from a parent variable. That's why I thought of using the chain and wondered if a way existed. Thanks for the great advice.
If you really want to, anything is possible :
Of the top of my head, you could try to do something like this :
var sectionTable,
sectionTableRows,
sectionTableColumns = $('td', (sectionTableRows = $('tr',(sectionTable = $('#sectionsTable')))));
Another ideea would be to build a mini-plugin that assigns the current jquery object to a certain field of an object :
jQuery.fn.assignTo = function(variableName,namespace){
var ns = namespace || window;
ns[variableName] = this;
return this;
}
With this peace of code you could do the following :
var sections = {};
jQuery("#sectionsTable")
.assignTo('sectionTable',sections)
.find("tr")
.assignTo('sectionTableRows',sections)
.find("td")
.assignTo('sectionTableColumns',sections);
console.log(sections.sectionTable);
console.log(sections.sectionTableRows);
console.log(sections.sectionTableColumns);
Of course, if you do not specify any namespace, the variables will be global (will be attached to the window object);
Any way, I do not encourage you to use these examples, because it doesn't make very much sense to worsen your code's readability in favour of fewer equal signs and var declarations.
I maybe don't really understand what you want or need, but you can chain any function for a jQuery wrapped set and "end" it and therefor "go back" to the previous set. For instance:
jQuery("#sectionsTable").css('background-color', 'red')
.find('tr').css('background-color', 'yellow')
.find('td').css('background-color', 'black')
.end() // back to 'tr'
.doSomething()
.end() // back to '#sectionsTable'
.doSomething();
However, this would imply that you only need to access those elements once. If you need to access them later in your code, you always should store the results references in variables for several performance reasons.
You could rewrite it as follows:
var $sectionTable = $('#sectionsTable'),
$sectionTableRows = $('tr', $sectionTable),
$sectionTableColumns = $('td', $sectionTableRows);
But of course, that’s only useful if you’re actually gonna use all three of those variables.
The only thing comes to my mind is one-var declaration, like:
var sectionTable = jQuery("#sectionsTable"),
sectionTableRows = sectionTable.find("tr"),
sectionTableColumns = sectionTableRows.find("td");
Why would you want to?
What's wrong with defining the three variables?
(No, you can't).
If you didn't need the sectionTable or sectionTableRows variables at all, you could of course do;
var sectionTableColumns = jQuery("#sectionsTable").find("tr").find("td");
Which, using the descendant selector, could be shortened to just;
var sectionTableColumns = jQuery("#sectionsTable tr td");
Once again I found JavaScript code on the Internet that contains an inline function where, in my opinion, regular statements would make just as much sense. Here's the first sample:
function outerHTML(node){
// if IE, Chrome take the internal method otherwise build one
return node.outerHTML || (
function(n) {
var div = document.createElement('div'), h;
div.appendChild(n.cloneNode(true));
h = div.innerHTML;
div = null;
return h;
})(node);
}
If you'd ask me to code the same thing, it would look like this:
function outerHTML(node){
var div, h;
// if IE, Chrome take the internal method otherwise build one
if (node.outerHTML) {
return node.outerHTML;
}
div = document.createElement('div')
div.appendChild(node.cloneNode(true));
h = div.innerHTML;
div = null;
return h;
}
EDIT: As OverZealous stated, there is a difference in logic on this one. I leave it here so nobody gets confused about that answer.
And maybe another original sample (yes, this doesn't "compile" as it's just a code fragment):
addGetters: function (attributes) {
var that = this;
function addGetter(attr) {
that.prototype["get" + attr.capitalize()] = function() { return this[attr]; };
}
for(var i = 0; i < attributes.length; i++) {
var attr = attributes[i];
addGetter(attr);
}
},
compared to my attempt
addGetters: function (attributes) {
for(var i = 0; i < attributes.length; i++) {
var attr = attributes[i];
this.prototype["get" + attr.capitalize()] = function() { return this[attr]; };
}
},
Is there a difference? Doesn't the original version consume more space since a function needs to be created and/or isn't it slower because of this? Is there a possible memory leak?
The utilisation of CPU and memory is very important as I'm coding in an environment where both are limited and any "less" is good. And since there's no sizeof() in JavaScript and its implementation attempts aren't safe to interpret any thinking-ahead-fixes are important.
Please note that as far as the "my version" is concerned I didn't test it. I'm just trying to explain what I'm trying to ask.
EDIT: Even though this question has an answer, I'm still wondering about the memory utilisation. If somebody has some insights, please don't hesitate to add it here.
For the first one, I don't believe there is any reason for the function. It might have (d)evolved into that state through small changes, but the extra function wrapper isn't providing any benefit that I can see.
The second example, however, is actually critical to use the function wrapper. The reason is due to JavaScript's (sometimes frustrating) function-level scope. In your example, there is only one attr variable. It is shared across the different attributes. This means that, in the end, every attribute will return the value of last attribute in the array.
e.g:
var attrs = ['foo', 'bar', 'baz']
obj.addGetters(attrs);
obj.getFoo(); // returns obj.baz
obj.getBar(); // returns obj.baz
By wrapping the getter creation in a function, you eliminate that issue, because attr ends up being scoped to the creating function. This is why Douglas Crockford's JSLint says "Don't create a function inside a loop". It leads to unexpected bugs like that one.
As OverZealous pointed out, one needs to be sure about the logic that's happening. +1 for that.
As far as the performance is concerned I finally had the time to do some testing on my own. However, I'm working in an environment where I can't really check memory utilisation. So I tried to fool around with the performance.
The result is that it may have an impact depending on how often this feature is used. On my target system the simple creation of an inline function that does close to nothing, e.g.
myArray.each(function inlineFunc(el) { return el; });
takes about 1.8 seconds for 10,000 creations of such a function (in the example above myArray had no elements). Just in comparison the PC-version of that browser needs 1,000,000 iterations to get somewhere close to that (obviously this also depends on the hardware).
Since the 10,000 iterations are reached in the code we use (not directly in one loop, but functions are created all over the code), we will have a word with our subcontractor.
The answer lies in the eye of the beholder.
It's a matter of preference.
It's up to you if you put "speed" above modularity.
Ask yourself this: why do you use a for when it can be done with a while? It is proven that in some cases the while structure is a bit faster.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Why avoid increment (“++”) and decrement (“--”) operators in JavaScript?
I'm a big fan of Douglas Crockford and his excellent book, JavaScript: The Good Parts. I also use his JSLint tool on an hourly basis before checking in any code to our repository, as is good sense.
One thing I've noticed when running code through JSLint is its insistence that the ++ increment operator is somehow evil. I know I can turn certain rules off, but that's cheating ;). Crockford mentions his dislike on page 112 of JS: TGP...
In my own practice, I observed that when I used ++ and --, my code tended to be too tight, too tricky, too cryptic. So, as a matter of discipline, I don't use them any more. I think that as a result, my coding style has become cleaner.
That's all very lovely, but he doesn't give any examples of the way he codes them now. I assume he's doing something like...
var i;
i = 0;
i = i + 1;
Again, great, but I've got a few basic 'for loops' in my JS code, as I imagine many people have, and I've always used the standard syntax...
for (i = 0; i < myArray.length; i++) {
// Loop Stuff
}
Am I missing something? What's the cleanest and/or best way to increment/decrement?
I think this is rather controversial, and I personally stick to i++ in loops. Of cource, you can replace it with i = i + 1 in your loop statement, to be fully compliant to JSLint.
There aren't real alternatives to increment and decrement numerical values in JavaScript. You can often use Array.forEach() and/or Object.keys() in order to prevent numerical indexes.
The only tricky thing I see in autoincrement/decrement operators (and I'm quite surprised that no one here pointed that out) is the difference between prefix (++i) and postfix (i++) versions. I also believe that autoincrement/decrement operators are slightly more efficient, in general. Besides this, I think the choice is based mainly on aesthetics, especially in javascript.
to pass JSLint I now always do:
for (var i = 0; i < myArray.length; i+=1) {
// Loop Stuff
}
In C/C++ this is important, especially with arbitrary iterators and pre/post increment semantics. Also, random access vs forward-iterators.
In Javascript it's more about aesthetics than anything else. Unless you're dealing with strings. "1"+1 is "11".
I would say that ++i is an idiom that's worth being consistent with.
JSLint is wrong.
Personally, I see nothing wrong with the ++/-- operators for incrementing and decrementing. While something like i = i + 1; may be easier for new coders, the practice is not rocket science once you know what the operators stand for.
Regarding loop, one original idea can be using such loop to avoid all kinds of numbers:
var a = [];
for (var i in " ")
a.push("Loop iteration here");
alert(a.join("\n"));
Meaning iterate over a string, there will be amount of iterations equal to the string length - 5 in the above example.
Live test case: http://jsfiddle.net/vTFDP/
Given some JS code like that one here:
for (var i = 0; i < document.getElementsByName('scale_select').length; i++) {
document.getElementsByName('scale_select')[i].onclick = vSetScale;
}
Would the code be faster if we put the result of getElementsByName into a variable before the loop and then use the variable after that?
I am not sure how large the effect is in real life, with the result from getElementsByName typically having < 10 items. I'd like to understand the underlying mechanics anyway.
Also, if there's anything else noteworthy about the two options, please tell me.
Definitely. The memory required to store that would only be a pointer to a DOM object and that's significantly less painful than doing a DOM search each time you need to use something!
Idealish code:
var scale_select = document.getElementsByName('scale_select');
for (var i = 0; i < scale_select.length; i++)
scale_select[i].onclick = vSetScale;
Caching the property lookup might help some, but caching the length of the array before starting the loop has proven to be faster.
So declaring a variable in the loop that holds the value of the scale_select.length would speed up the entire loop some.
var scale_select = document.getElementsByName('scale_select');
for (var i = 0, al=scale_select.length; i < al; i++)
scale_select[i].onclick = vSetScale;
A smart implementation of DOM would do its own caching, invalidating the cache when something changes. But not all DOMs today can be counted on to be this smart (cough IE cough) so it's best if you do this yourself.
In principle, would the code be faster if we put the result of getElementsByName into a variable before the loop and then use the variable after that?
yes.
Use variables. They're not very expensive in JavaScript and function calls are definitely slower. If you loop at least 5 times over document.getElementById() use a variable. The idea here is not only the function call is slow but this specific function is very slow as it tries to locate the element with the given id in the DOM.
There's no point storing the scaleSelect.length in a separate variable; it's actually already in one - scaleSelect.length is just an attribute of the scaleSelect array, and as such it's as quick to access as any other static variable.
I think so. Everytime it loops, the engine needs to re-evaluate the document.getElementsByName statement.
On the other hand, if the the value is saved in a variable, than it allready has the value.
# Oli
Caching the length property of the elements fetched in a variable is also a good idea:
var scaleSelect = document.getElementsByName('scale_select');
var scaleSelectLength = scaleSelect.length;
for (var i = 0; i < scaleSelectLength; i += 1)
{
// scaleSelect[i]
}