weird syntax for "for" loop - javascript

Today I came across the following JS:
for (var b = k, d = function (c) {
// function body
}, a = b.p, e = z; 0 < c;) {
} // for loop closing cause
Can some please explain what's happening here? I'm confused about the function, normal "for" loop would do:
for(x=0; x<something; x++){
}
This loops appears to follow a different structure:
for(x=0; d = function(c), a = somevar, e = somevar, 0 < c)
Why are there 5 elements in the for loop? Thanks!

for (var b = k, d = function (c) {}, a = b.p, e = z; 0 < c;) {
} // for loop closing cause
for(x=0; x<something; x++)
If you map the first for loop with the signature for loop...
The code in bold is the declaration part for different variables that are going to be used inside the for loop.. .. Any number of variables can be declared here...
The second is the check condition...
And the third part is empty

There are not five parts, only three:
The first one contains four variable declarations (b, d, a and e).
The second one contains a comparison (0 < c).
The third one is empty.
Each part is separated by semicolons (;) and the variable declarations are separated by commas ,.
The first part is allowed to contain either an expression or a variable declaration list. For more information, have a look at the specification or the MDN JavaScript documentation:
initialization
An expression (including assignment expressions) or variable declaration. Typically used to initialize a counter variable. This expression may optionally declare new variables with the var keyword. These variables are not local to the loop, i.e. they are in the same scope the for loop is in. The result of this expression is discarded.
Only because for(x=0; x<something; x++) is the most typical form, does not mean others don't exist. Each part can contain an arbitrary expression. For example, a useful way to iterate over all children of a DOM element is the following:
for(var node = element.firstChild; node; node = node.nextSibling) {
}
First, node is initialised with the first child of the element. The second part just tests whether node is not null (you could also write node !== null explicitly) and the third part (executed after the iteration) assigns the next child to node.

Ill explain, but basically this is not good code.
Its not good code because you need to go online just to figure it out.
for (var b = k, d = function (c) {
// function body
}, a = b.p, e = z; 0 < c;) {
} // for loop closing cause
is the equivalent of
var b = k,
d = function (c) {
// function body
},
a = b.p,
e = z;
for (; 0 < c; ){
}
for loop parents has three parts
1. Initialization
2. Condition
3. Ending statement
That must all be separated by a ;
except these are all optional in a for loop
for (var init = 0; init < 10; init += 1) {}
same as:
var init = 0;
for (;;) {
if (!(init < 10)) {
break;
}
init += 10;
}

The control variables in a loop can also be a valid expressions as you have in your example.

The first loop you posted is slightly different from the last. The first declares and assigns several variables (one of which is a function), then provides a condition (0<c), then does nothing every iteration. The last seems invalid.
The problem with the first one seems to be only that it does not intialize a c, so unless c is a variable from outside of the scope of the loop that is somehow being changed inside its body, the loop will either not run at all (if c>=0) or it will run forever (if c is indeed less than 0).

for (var b = k, d = function (c) {
// function body
}, a = b.p, e = z; 0 < c;) {
} // for loop closing cause
as long as d is not 0 the for loop will run. d is 0 when 0 < c

Related

Is there a difference between a for loop without increment vs. one with a non incremented variable?

In JS, is there any difference between the following two types of loops?
A for loop without an increment such as:
for (i = 0; i < 1000;) { // i will be changed inside the block
vs
A for loop with a variable defined, but one that is not being incremented? Like this:
for (i = 0; i < 1000; i) { // i changed inside block
I saw this strange construct in several Stack Overflow questions.
i meant to note the i variable changes, not that i myself changed something or that i have been changed in some way.
Under normal circumstances: no, there is no difference.
The for statement creates a loop that consists of three optional
expressions, enclosed in parentheses and separated by semicolons,
followed by a statement (usually a block statement) to be
executed in the loop.
The three expressions (initialization, condition and final-expression) are all optional (unlike the semicolons themselves), so if you omit the final-expression (which is most commonly used to increment the i/index/counter) that part simply will not be used.
If you use an isolated i as the final-expression, then this will be evaluated after every iteration of the for-loop. But an isolated variable on its own usually doesn't have any side effects. The value wont change and the value that is returned by the i expression (the value of i) is ignored in case of the final-expression.
console.log('For loop without final-expression:');
for (let i = 0; i < 10;) {
console.log(i++);
}
console.log('For loop with final-expression:');
for (let i = 0; i < 10; i) {
console.log(i++);
}
But that is all under normal circumstances. There are cases where it does make a difference, but you really should never encounter this in production-ready code.
const target = {
i: null,
};
const proxy = new Proxy(target, {
get(target, prop) {
if (prop === 'i') {
return target._i++;
}
return Reflect.get(...arguments)
},
set(target, prop, value) {
if (prop === 'i') {
target._i = value;
} else {
return Reflect.set(...arguments);
}
}
});
with(proxy) {
console.log('For loop without final-expression:');
for (i = 0; i < 10;) {
console.log("loop");
}
console.log('For loop with final-expression:');
for (i = 0; i < 10; i) {
console.log("loop");
}
}
In the above example I used a Proxy to be able to intercept all access to the properties of an object and I used a with statement so that every variable is treated as a property of this proxied object. As a result, when i is read, the getter of the proxy is called, and I increment the value of i every time this happens.
In for (i = 0; i < 10; i), i is set once at i = 0 and read twice in i < 10 and the final-expression i. Because it is read twice, the i will be incremented twice, so the loop will only iterate 5 times. In the other for (i = 0; i < 10;) loop i is only read once, so the loop will iterate 10 times.
There are likely more ways to achieve a similar effect, but again you should really never encounter this in production ready code, so it shouldn't be taken into account when deciding if you want to keep the i in the final-expression or not.
Personally I would say that if you don't use an optional expression, then you should leave it out. Especially because when glancing over the code, i can be misread as i++ which might confuse the reader. But in the end it is a matter of taste.

Number prototype

Hi everyone i need an help.
I try to modify Number.prototype to add the function sum.
I want to add some numbers to my initial number.
Number.prototype.sum = async (...nums) => {
var x = //What I have to write to have my inizial number here?
for (var i = 0;i<nums.length;i++) {
x=x+nums[i]
}
return x
}
console.log((10).sum(2)) // output: 12
console.log((10).sum(4,6)) // output: 20
(I use visual studio code and the hint after this. is only number)
I tried with:
Number.prototype.valueOf(this)
Number.prototype.valueOf(this.number)
Number.parseInt(this.toString())
Number.parseFloat(this.toString())
Number.parseInt(this.number.toString())
Number.parseFloat(this.number.toString())
this.valueOf()
this.number.valueOf()
You have to use function to access the correct this context (which is the number that the method is called on). Arrow functions inherit their this context from the parent scope (the global object in this case). Also async is not needed since you are not doing anything asynchronous here:
Number.prototype.sum = function (...nums) {
var x = this
for (var i = 0; i < nums.length; i++) {
x = x + nums[i]
}
return x
}
console.log((1).sum(2, 3))
Aside from the fact that augmenting native prototypes is a bad idea, wouldn't you think that a function like this is better suited for the Array prototype?

a.push is not a function; a.shift is not a function; a.splice is not a function

I have looked around, and have not been able to figure out why I'm throwing this error on this simple rotation algorithm. Happens with .push, .shift, .splice. Pls help! (I am aware there are more efficient ways to solve, just want to understand why I can't get these methods to work!)
function rotation(n, d) {
var a = []
for (i = 1; i <= n; i++) {
a += i
};
for (x = 1; x <= d; x++) {
a.push(a[0]);
a.shift();
}
console.log(a)
}
rotation(5, 4)
a += i means a = a + i. + has no special meaning for arrays. By using +, you're coercing to a primitive — a string, in this case — and doing string concatenation. Since then a refers to a string, not an array, it doesn't have array methods.
If you want to add an element, use push, not +:
for(i=1; i <= n; i++){
a.push(i);
}
Also note that semicolons (;) don't go at the end of control-flow statements with blocks attached, and do go at the end of all other statements (for instance, your original a += i, the console.log near the end, etc.).

How to create closure in loop and store it in variable for later execution

See code below. I've tried to strip it to its bare bones.
I have a _queue array. I want to iterate 10 times. On each iteration, I want to create a function that has a properly scoped reference for j (i.e. j=0 on the first iteration, j=1 on the second iteration, etc.)
I want to store that function in variable f, and then add f to the _queue array so I can call it later.
The problem of course is that on each iteration of the first loop, instead of storing the closure in f, it immediately executes the closure.
My question is this: How do I store the function with its proper j variable so that I can add it to the _queue array?
_queue = [];
for (j = 0; j < 10; j++) {
var f =
(function (index) {
alert(index);
})(j); //code is executed here instead of stored in the f variable
_queue.push(f); //Add f
}
for (k = 0; k < _queue.length; k++){
_queue[k].call();
}
Using an immediate function (or in general using a function) to introduce a new scope is correct. But you have to return a function from the immediate function:
var f = (function (index) {
return function() {
alert(index);
};
}(j));

The "unexpected ++" error in jslint [duplicate]

This question already has answers here:
Why avoid increment ("++") and decrement ("--") operators in JavaScript?
(17 answers)
Closed 5 years ago.
What is the best practice for that then?
Jslint explains that it "adds confusion". I don't see it really...
EDIT: The code, as requested:
var all,l,elements,e;
all = inElement.getElementsByTagName('*');
l = all.length;
elements = [];
for (e = 0; e < l; (e++))
{
if (findIn)
{
if (all[e].className.indexOf(className) > 0)
{
elements[elements.length] = all[e];
}
} else {
if (all[e].className === className)
{
elements[elements.length] = all[e];
}
}
}
The longstanding best practice: use i += 1 instead, following jslint's advice.
As for why it is a better practice than ++, according to Crockford:
The increment ++ and decrement -- operators make it possible to write in an extremely terse style. In languages such as C, they made it possible to write one-liners that: for (p = src, q = dest; !*p; p++, q++) *q = *p; Most of the buffer overrun bugs that created terrible security vulnerabilities were due to code like this. 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.
Edit: Included comment from Nope as this answer continues to get views.
Just add /*jslint plusplus: true */ in front of your javascript file.
To avoid confusion, and possible problems when using minifiers, always wrap parens around the operator and its operand when used together with the same (+ or -).
var i = 0, j = 0;
alert(i++ +j);
This adds i and j (and increments i as a side effect) resulting in 0 being alerted.
But what is someone comes along and moves the space?
var i = 0, j = 0;
alert(i+ ++j);
Now this first increments j, and then adds i to the new value of j, resulting in 1 being alerted.
This could easily be solved by doing
var i = 0, j = 0;
alert((i++) +j);
Now this cannot be mistaken.
Personally, I prefer to put statements such as i++ on a line by themselves. Including them as part of a larger statement can cause confusion for those who aren't sure what the line's supposed to be doing.
For example, instead of:
value = func(i++ * 3);
I would do this:
value = func(i * 3);
i++;
It also means people don't have to remember how i++ and ++i work, and removes the need to apply quite so many preference rules.
The real problem of the ++ operator is that it is an operator with side effects and thus it is totally opposed to the principle of functional programming.
The "functional" way to implement i++ would be i = i + 1 where you explicitly reassign the variable with no side effects and then use it.
The possibility of confusion is that ++ does two things by adding a value AND reassigning it to the variable.
JSLint friendly loop
for (i = 0; i < 10; i += 1) {
//Do somthing
}
Please note that the ++ operator depends on position with respect to the prior/next variable and the newline / semicolon to determine order of operations.
var a = 1;
var b = a++;
console.log(b); // b = 1
console.log(a); // a = 2
var a = 1;
var b = ++a;
console.log(b); // b = 2
console.log(a); // a = 2
There is something called a pre-increment: ++i and a post-increment i++
and there is a difference:
var i = 9;
alert(++i); //-> alerts 10
var j = 9;
alert(j++); //-> alerts 9
alert(j); //-> alerts 10 now, as expected
var k = 9;
alert((k++)); //-> still alerts 9 even with extra parentheses

Categories

Resources