3

I came across this snippet reading MDN's tutorial "A re-introduction to JavaScript (JS tutorial)":

function countChars(elm) {
 if (elm.nodeType == 3) { // TEXT_NODE
 return elm.nodeValue.length;
 }
 var count = 0;
 for (var i = 0, child; child = elm.childNodes[i]; i++) {
 count += countChars(child);
 }
 return count;
}

What I don't understand is the for loop statement. Specifically, the condition statement child = elm.childNodes[i]. I always learned that the condition in a loop should be a logical one. For me, that's an assignment.

What am I losing?

asked Sep 4, 2017 at 21:11
1
  • Assignment always returns the assigned value. If the element is not found, it would be null, or in this case undefined, and as null and undefined are both falsy, the assigment, or rather the assigned value it returns, can also be used as a condition. Commented Sep 4, 2017 at 21:15

4 Answers 4

5

When the i in child = elm.childNodes[i] is bigger than the length of the array, the deklaration gets evalutated to undefined. And in js undefined is equal to false Boolean(undefined) -> false.

Because of that, this is a boolean equation.

That kind of equation is danger because if the array contains an element that is equal to false (null, 0, false), the loop will stop without iterating all elements.

answered Sep 4, 2017 at 21:14
Sign up to request clarification or add additional context in comments.

6 Comments

It's not equal to false, it's falsy, which is different ! As childNodes returns elements, it would never return false or 0
Boolean(undefined) === false -> true Thats feels like equal for me
@adeneo var a=[false]; for(var i =0; child = a[i]; i++){ console.log("this will never be seen")} in this case it returns false with the first element.
But undefined === false is not true, so it's not strictly equal unless you convert it to a boolean, which means it's not equal, it's falsy, not false
In your second example, passing in 0 will of course void the loop, but childNodes doesn't return zeros, it returns DOM nodes
|
2

The condition of for loop here is the value of the assignment oprator = (which is in other words the value elm.childNodes[i]).

var a,
 assignmentOperatorValue = ( a = 5 );
// ^^^^^^^^^ this yields 5 which is then assigned to assignmentOperatorValue, you can even pass that value to a function like: func(a = 5);
 
console.log(assignmentOperatorValue);

If elm.childNodes[i] is an element (truthy value) then the condition is true.

If elm.childNodes[i] is undefined (falsy value) then the condition is false.

answered Sep 4, 2017 at 21:14

Comments

1

for loops are built by 3 parts:

  • initialization
  • condition
  • final-expression

In your case - the condition part is child = elm.childNodes[i];.

When accessing element of list that is our-of-range - the value you will get is undefined and the condition will result in breaking the loop.

answered Sep 4, 2017 at 21:16

Comments

1

You're right to recognize that this is an assignment, and I personally would avoid writing a loop like this because it can be confusing to other developers. However, it actually works because every assignment expression returns the value that was assigned. For example, after the following statement, both a and b will have a value of 1:

var a, b;
a = b = 1;

If elm.childNodes is an array, then child = elm.childNodes[i] will both assign child's value and return the value of elm.childNodes[i]. If elm.childNodes[i] is truthy, then the loop will continue. Otherwise it will break.

So this loop could break when it reaches an index higher than the last value in the array, or if the value at an index is 0, false, null or any other falsy value in the JavaScript language. It's likely that the programmer is just assuming that all values in the array will have to be valid objects that won't evaluate to false.

answered Sep 4, 2017 at 21:15

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.