Reputation: 677
I come across this code below which add a specified property value of all block of a nested object to an array called arrays. My problem is that I don' t understand how iteration works in a nested object like the one below using for loop.
Can someone explain to me how for loop iteration is possible with an object?
let list = {
value: 1,
rest: {
value: 2,
rest: {
value: 3,
rest: null
}
}
};
below is the function that does the job
function listToArray(list) {
let arrays = [];
for (let node = list; node; node = node.rest) { // big question: how it works or possible?
arrays.push(node.value);
}
return arrays;
}
console.log(listToArray(list)); // -> [1, 2, 3]
Upvotes: 5
Views: 572
Reputation: 31712
How do for
loops work:
First you need to understand how for
loops works.
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. MDN
The for
loop has this structure:
for ([initialization]; [condition]; [final-expression])
statement
The expressions initialization
, condition
and final-expression
could be any valid expression. Any or all of these expressions could be omitted (for(;;)
is valid in javascript and it creates an infinite loop).
The for
loop begins by executing the initialization
expression if specified, then repeats the following actions: check if the condition
is truthy, if so then it executes statement
(s) and final-expression
in order, if the condition
is falsy it stops looping.
Here is an example, the following diagram (image source):
Corresponds to the follwing for
loop:
for(i = 2; i <= 6; i = i + 2)
print i + 1
Notice that the initialization
part i = 2
is only executed once whereas the rest (the condition
part i <= 6
, the statement
(s) part and the final-expression
i = i + 2
) could be executed multiple times (in order) depending on the condition
.
Explanation of the code in question:
for (let node = list; node; node = node.rest) { // big question: how it works or possible?
arrays.push(node.value);
}
The initialization
part of this loop just declares the variable node
and sets its value to the root element list
, this part is only executed once, when the loop is about to start.
The condition
part checks whether node
(the variable) is truthy or not, in javascript an object is truthy whereas undefined
is not, it's a falsy value (there are other truthy and falsy values of course but we are only interested in these two for this particular example). The concept of the loop is running down the object from node to node (see the final-expression
part bellow). When a child node exists, the next value of node
will be that node (which is an object), that means it's gonna be a truthy value, hence the condition will be true. Whereas if the child node doesn't exists, node
will be undefined
(a falsy value) and thus the condition will be falsy.
The final-expression
just sets the value of node
to the child node of the current node which is node.rest
. If it exists node
will be an object, otherwise it will be undefined
.
Upvotes: 4
Reputation: 17190
As an introduction, first note the for loop has the following syntax:
for (statement 1; statement 2; statement 3) {
// code block to be executed
}
Statement 1
is executed (one time) before the execution of the code block.Statement 2
defines the condition for executing the code block.Statement 3
is executed (every time) after the code block has been executed.
So, on every iteration you are going one level deep of the tree
with node = node.rest
. The loop stops because eventually you will try to access property rest
on some node
that don't have that key or is set to null
, this will be evaluated to undefined
or null
respectively, and since the stop condition of the for
loop is to test the variable node
it will stop when this is undefined
or null
(Note these are falsy values on Javascript).
Example with debug:
let list = {
value: 1,
rest: {
value: 2,
rest: {
value: 3,
rest: null
}
}
};
function listToArray(list)
{
let arrays = [];
for (let node = list; node; node = node.rest)
{
console.log("Current node is: " + JSON.stringify(node));
console.log("Node value is: " + node.value);
arrays.push(node.value);
console.log("Next node will be: " + JSON.stringify(node.rest));
}
return arrays;
}
console.log(listToArray(list));
Upvotes: 1
Reputation: 410
For loop consists of three parts
let node=list
) node
)true
. Usually you want to update a variable created in the 1Let's have a closer look at what is actually happening here:
for(let node = list; node; node=node.rest)
First, you are creating a new variable called node
with the value of list
Next, you are checking if your isn't currently null
or undefined
. Theese two values are falsy, which means they both returns false
when they are coerced to a boolean. If it's not, your arrays.push
will be executed, otherwise your loop will be terminated.
Last, you are updating your node
with a value of the node.rest
. Before your arrays.push
will be executed with the updated node
, your condition will be checked again.
Finally, when your node
is
{
value: 3,
rest: null
}
your 3 part of the loop will update the node
variable assigning rest
to it, which is null
and your 2 won't pass, so it'll be terminated
Upvotes: 1
Reputation: 138567
Let's say you want to access the nested object containing value: 3
. Then you'd do:
list.rest.rest // { value: 3, rest: null }
You could also write that into multiple lines as:
let node = list; // { value: 1, rest: { ... } }
node = node.rest; // { value: 2, rest: { ... } }
node = node.rest; // { value: 3, rest: null }
and that can be generalized for n repetitions as
for(let node = list; node; node = node.rest) {
//...
}
Real world example:
You are living in a small village, there is only one street from north to south. There are a few houses next to the street. You are living at the end of the small town, at the northern end. Your neighbour's name is Bob. Bob also got a neighbour called Alice. Alice got a neighbour called Eve. Now if you want to walk along the street , you could either visit Bob, then Alice, then Eve. Or you just walk to the next house until you reached te end of the little town.
const bob = you.southernNeighbour;
const alice = bob.southernNeighbour;
const eve = alice.southernNeighbour;
// ...
let current = you; // you start where you are.
while(current) // as long as there is a house, walk
current = current.southernNeighbour; // go to the next southern neighbour
Upvotes: 0
Reputation: 18561
for
can be viewed as a syntactical sugar for while
, even if there are a few low-level differences, these are the same:
for (let i=0; i<10; i++) {
console.log(i);
}
let i=0;
while(i<10) {
console.log(i);
i++;
}
The syntax of for
is for(initialization, test, iteration)
. This:
for (let node = list; node; node = node.rest) { doSomething(node); }
Is perhaps easier to understand if written as this:
let node = list;
while(node) { // equivalent to: while(node!==null) {
doSomething(node);
node = node.rest;
}
Upvotes: 0
Reputation: 48751
You can also make this recursive, as this makes it easier to explain.
If your object is null
, just return the array (as it stands), else return a call to the next rest
and add the value
to the array.
obj = { value: 1, rest: {...} }, arr = [] // Add 1 to arr and return obj.rest
obj = { value: 2, rest: {...} }, arr = [ 1 ] // Add 2 to arr and return obj.rest
obj = { value: 3, rest: null }, arr = [ 1, 2 ] // Add 3 to arr and return null
obj = null, arr = [ 1, 2, 3 ] // Return arr [ 1, 2, 3 ]
let list = {
value: 1,
rest: {
value: 2,
rest: {
value: 3,
rest: null
}
}
};
function listToArray(obj, arr = []) {
return obj == null ? arr : listToArray(obj.rest, arr.concat(obj.value));
}
console.log(listToArray(list)); // -> [1, 2, 3]
.as-console-wrapper { top: 0; max-height: 100% !important; }
Upvotes: 0