Why can't I assign for loop to a variable? - javascript

So I am just wondering why the following code dosen't work. I am looking for a similar strategy to put the for loop in a variable.
var whatever = for (i=1;i<6;i++) {
console.log(i)
};
Thanks!

Because a for loop is a statement and in JavaScript statements don't have values. It's simply not something provided for in the syntax and semantics of the language.
In some languages, every statement is treated as an expression (Erlang for example). In others, that's not the case. JavaScript is in the latter category.
It's kind-of like asking why horses have long stringy tails and no wings.
edit — look into things like the Underscore library or the "modern" add-ons to the Array prototype for "map" and "reduce" and "forEach" functionality. Those allow iterative operations in an expression evaluation context (at a cost, of course).

I suppose what you look for is function:
var whatever = function(min, max) {
for (var i = min; i < max; ++i) {
console.log(i);
}
}
... and later ...
whatever(1, 6);
This approach allows you to encapsulate the loop (or any other code, even declaring another functions) within a variable.

Your issue is that for loops do not return values. You could construct an array with enough elements to hold all the iterations of your loop, then assign to it within the loop:
arry[j++] = i;

You can do this, but it seems that you might want to check out anonymous functions. With an anonymous function you could do this:
var whatever = function(){
for (var i=1;i<6;i++) {
console.log(i);
}
};
and then
whatever(); //runs console.log(i) i times.

Related

How to remove the `let` reassignment in a `for` block

I am trying to remove the let reassignment in the below function within a for block scope.
I want to accumulate the value within the block scope of for loop but not to access a closure or global variable(totalValue) which is outside of for loop block scope.
Because it makes the code more readable and maintainable for bigger functions.
I am looking for any alternate way which removes the let re-assignment pattern as shown below to acheive the same functionality.
function howToRemoveLetReassignmentForTheBelowScenario(target: number) {
let totalValue: number = 0;
for (
let i = 0;
i < target; // iteration is happening based on a condition where both variables are of number type. Wanted to highlight the point that there is no array.
i++
) {
const calculatedValueForEachIteration: number = i + Math.random()
totalValue += calculatedValueForEachIteration; // `let` re-assignmnet hapening here.
}
return totalValue
}
Playground link
Using Array(n) you can use reduce:
const target = 10;
const totalValue = [...Array(target).keys()]
.reduce((acc, value) =>
acc += (value + Math.random())
);
console.log(totalValue);
I don't think there is a way using "for" loop. How do we return the variable out of for loop if the variable scope is only within for loop? "for" is not a function that returns something.
I'm not quite sure what you mean by 'let reassignment pattern'. Your options are either a loop (for, while) or using array reduce as in other answers. My opinion is that the for loop is more readable than creating an array and using array reduce. I don't know if this is just because I am relatively new to JavaScript. You're still going to need to run the same code in a loop to calculate the subtotal (subTotal += newValue). I feel that, as a reader, it is quite apparent what is happening in your code - the function is written well, defining variables at the right scope, and performing a single, simple task). It just needs a name that describes the functionality to make it immediately apparent to the user.
Another possible consideration is that (from a few tests with a target of 1000), a for loop comes in at 0.02ms and creating an array and then performing an array reduce takes between 0.14ms and 0.7ms. While 0.7ms is still small, it seems like a sacrifice to gain little readability.
If you're really concerned about readability, I would recommend using a class with a self-explanatory name and clear method names. This makes the functionality really understandable when a reader looks at it:
class Accumulator {
#subtotal = 0;
add(n: number) {
this.#subtotal += n;
}
getTotal() {
return this.#subtotal;
}
}
function sumConsecutiveNumbers(from: number, to: number) {
let accumulator = new Accumulator();
for (let i=from; i <= to; i++) accumulator.add(i);
return accumulator.getTotal();
}

Is this is a valid pattern and what is it called?

I find myself writing the following JavaScript more and more and I would like to know if this is a common pattern and if so, what is it called?
Part of the code and pattern:
var fruits = ["pear", "apple", "banana"];
var getNextFruit = function() {
var _index = 0,
_numberOfFruits = fruits.length;
getNextFruit = function() {
render(fruits[_index]);
_index = (_index + 1) % _numberOfFruits;
}
getNextFruit();
};
I have a function which takes no parameters, inside the function I redefine the function and immediately call it. In a functional language this might be a function being returned, JavaScript just makes it easier because you can reuse the name of the function. Thus you are able to extend the functionality without having to change your implementation.
I can also imagine this pattern to be very useful for memoization where your "cache" is the state we wrap around.
I even sometimes implement this with a get or a set method on the function where I can get the state if it's meaningful. The added fiddle shows an example of this.
Because this is a primarily JavaScript oriented question: The obligatory fiddle
I have a function which takes no parameters, inside the function I redefine the function and immediately call it.
Is this is a valid pattern and what is it called?
A function redefining itself is usually an antipattern, as it complicates stuff a lot. Yes, it sometimes can be more efficient to swap out the whole function than to put an if (alreadyInitialised) condition inside the function, but it's very rarely worth it. When you need to optimise performance, you can try and benchmark both approaches, but otherwise the advice is to keep it as simple as you can.
The pattern "initialises itself on the first call" is known as laziness for pure computations (in functional programming) and as a singleton for objects (in OOP).
However, most of the time there's no reason to defer the initialisation of the object/function/module whatever until it is used for the first time. The ressources taken for it (both time and memory) are insignificant, especially when you are sure that you will need it in your program at least once. For that, use an IIFE in JavaScript, which is also known as the module pattern when creating an object.
Creating a function via a closure is a pretty common pattern in JavaScript. I would personally do that differently:
var fruits = ["pear", "apple", "banana"];
var getNextFruit = function(fruits) {
var index = 0,
numberOfFruits = fruits.length;
function getNextFruit() {
render(fruits[_index]);
index = (_index + 1) % numberOfFruits;
}
return getNextFruit;
}(fruits);
There's no good reason (in my opinion) to clutter up the variable names with leading underscores because they're private to the closure anyway. The above also does not couple the workings of the closure with the external variable name. My version can be made a reusable service:
function fruitGetter(fruits) {
var index = 0, numberOfFruits = fruits.length;
function getNextFruit() {
render(fruits[_index]);
index = (_index + 1) % numberOfFruits;
}
return getNextFruit;
}
// ...
var getNextFruit = fruitGetter(someFruits);
var otherFruits = fruitGetter(["kumquat", "lychee", "mango"]);

Efficiency of Javascript functions

Q1. I would like to confirm whether Version 1 of below code is more efficient than Version 2? I'd like to know for future reference so I will be writing codes according to the style of either V1 or V2.
Q2. How does one measure efficiency of the code? (Doesn't have to be in depth, I just want to have a rough idea)
Version 1:
function average(array) {
return array.reduce(function(a,b) { return a + b; }) / array.length;
}
Version 2:
function average(array) {
function plus(a,b) { return a + b; }
return array.reduce(plus) / array.length;
}
Edit: assuming that at a later stage I would be writing much more complex code and I would like to get into the habit of writing efficient code now. I know that for simple one-liners there's no explicit difference.
These functions are equally efficient from a big-O perspective. The reason they are the same, is that they both pass a function into reduce() (the way in which the function is declared is different, but it's the same underlying structure and thus the same efficiency). The functions are otherwise the same. If I were you, I'd opt for the second case as it is probably easier to maintain.
If you want, you can use a speed test, but honestly it's a waste of your time as these two approaches are identical.
With a sequential loop, it's far faster:
http://jsperf.com/anonymous-vs-named-function-passing/2
function average3(array) {
var sum =0;
for( var i=0, len=array.length; i< len; i++ )
sum+=array[i];
return sum/array.length;
}
You will have the same result. Or difference will be negligible. Depends on JS engine and how good its optimizer is.
As others suggested you can use jsperf.com for speed tests.
But if you really care about performance then check third case here
http://jsperf.com/anonymous-vs-named-function-passing/3
They are the same... but you could optimize by avoiding to create a new closure of the sum function.
function sum(a,b){
return a+b;
}
function average(array){
return array.reduce(sum) / array.length;
}
This way sum won't hold a reference to array in its context; and a new instance of sum with the context won't be necessary. Remember that a closure will hold a reference of the arguments of the function that contains it even if you don't use those arguments.
This means that a new function sum won't be instantiated every time that you call average.

Javascript for loop syntax

As javascript developers we all have to write a lot of for loops. Before a couple of months I saw an alternative syntax, which I really liked. However, I'm now interested, is there any other nice way.
Let's say that I have an array of data representing users in a system. What I did before is:
var users = [
{ name: "A"},
{ name: "B"},
{ name: "C"},
{ name: "D"},
{ name: "E"}
];
var numOfUsers = users.length;
for(var i=0; i<numOfUsers; i++) {
var user = users[i];
// ...
}
There is one additional row var user = users[i];. Normally I feel more comfortable if I have user instead of users[i]. So, the new way:
for(var i=0; user=users[i]; i++) {
// ...
}
I'm also wondering if the second approach produces problems in some of the browsers. One of my colleagues reported that this syntax is a little bit buggy under IE.
Edit:
Thankfully, the answers below pointed me out to the right direction. If some of the elements of the array is falsy then the loop will stop. There is some kind of solution:
for(var i=0; typeof (user=users[i]) !== "undefined"; i++) {
// ...
}
But that's too much for me. So, I guess that I'll use this syntax only when I'm 100% sure that all the elements are truly (which means never :)).
In your “new” approach, you don’t need numOfUsers any more.
As for the potential problems: This approach relies on all users[i] having values evaluating to true for the loop to continue (and user becoming undefined, equal to false and therefor ending the loop after the last user is processed) – but sometimes you might have data where not every record evaluates to true, but “false-y” values might also occur in the data – and in that case, this approach of course fails.
The problem with this approach:
for(var i=0; user=users[i]; i++) {
// ...
}
...is that it assumes user won't be "falsey" (0, "", null, undefined, NaN, or of course false) until you've gone past the end of the array. So it'll work well with an array of non-null object references, but if you then get in the habit of using it, it will bite you when you have an array of numbers, or strings, or such.
The other reason not to declare variables within the for construct is that it's misleading: Those variables are not scoped to the for loop, they're function-wide. (JavaScript's var doesn't have block scope, only function or global scope; ES6 will get let which will have block scope.)
On modern JavaScript engines (or with an "ES5 shim"), you can of course do this:
users.forEach(function(user) {
// ...
});
...which has the advantage of brevity and not having to declare i or numUsers or even user (since it's an argument to the iteration callback, and nicely scoped to that). If you're worried about the runtime cost of doing a function call for each entry, don't be. It'll be washed out by whatever actual work you're doing in the function.
I'm amazed if the second syntax works at all your middle operation should evaluate to true for each loop you want to complete and false as soon as you want to be done looping. As for any issues with your first for loop, a JavaScript is function scoped so that inner var statement will still leak to the containing function (as well as that i). This is different than most other languages that have block scoping. It's not so much of a problem but something to keep in mind if you are debugging.
If you are already using jQuery, you can use the jQuery.each function to loop over your arrays.
In any case you can look at the source code of that function and copy the relevant parts for your own foreach function: http://james.padolsey.com/jquery/#v=1.10.2&fn=jQuery.each

Javascript "Variable Variables": how to assign variable based on another variable?

I have a set of global counter variables in Javascript:
var counter_0 = 0;
var counter_1 = 0;
var counter_2 = 0;
etc
I then have a Javascript function that accepts an 'index' number that maps to those global counters. Inside this function, I need to read and write to those global counters using the 'index' value passed to the function.
Example of how I'd like it to work, but of course doesn't work at all:
function process(index) {
// do some processing
// if 'index' == 0, then this would be incrementing the counter_0 global variable
++counter_+index;
if (counter_+index == 13)
{
// do other stuff
}
}
I hope what I'm trying to accomplish is clear. If not I'll try to clarify. Thanks.
EDIT Clarification:
I'm not trying to increment the name of the counter, but rather the value the counter contains.
Looks like an array to me, or am I missing something?
var counters = [0,0,0];
function process(index) {
++counters[index];
/* or ++counters[index]+index, not sure what you want to do */
if (counters[index] === 13) {
/* do stuff */
}
}
function process(index) {
// do some processing
var counter;
eval('counter = ++counter_'+index);
if (counter == 13)
{
// do other stuff
}
}
Make sure that index really is an integer, otherwise mayhem could ensue.
Edit: Others have pointed out that you should use an array if you can. But if you are stuck with the named global variables then the above approach will work.
Edit: bobince points out that you can use the window object to access globals by name, and so deserves any credit for the following:
function process(index) {
// do some processing
var counter = ++window['counter_' + index];
if (counter == 13)
{
// do other stuff
}
}
Other answers have said "don't use eval()", but not why. Here's an explanation from MDC:
Don't use eval!
eval() is a dangerous function, which
executes the code it's passed with the
privileges of the caller. If you run
eval() with a string that could be
affected by a malicious party, you may
end up running malicious code on the
user's machine with the permissions of
your webpage / extension.
There are safe alternatives to eval()
for common use-cases.
The eval() javascript function will allow you to accomplish this. However it's generally frowned upon. Your question didn't explicitly exclude arrays. Arrays would definitely be more appropriate for the pattern you've described.

Categories