Problem Understanding Variables 🤯

Please take a look at the code below: -The code is intended to turn a string to Title Case string, link to the challenge: https://www.freecodecamp.org/learn/javascript-algorithms-and-data-structures/basic-algorithm-scripting/title-case-a-sentence-

function titleCase(string) {
  let splitstring = string.split(" ");
  for (let i of splitstring) {
    //variable spliti for '"split i", 'i' which is an entry of splitstring'
    let spliti = i.split("");
    spliti[0] = spliti[0].toUpperCase();
    i = spliti.join("");
    //console.log(i) = "expected Title Case string";
   //but for i=splitstring[0], i != splitstring[0],
   //i= "the expected result", but splitstring[0] the initial value
   // i didn't really understand whats happening
  }
  string = splitstring.join(" ");
  return string;
} 

My question is, isn’t the code in the for loop intended to change the array : splitstring? But it is not doing so, it is like the entries of splitstring array are changed inside the for loop but after that, the entries return to their intial value.

I removed my first answer because I didn’t think I was being as helpful as I could have been.

The i variable in the for loop is a copy of each array element in splitstring, so you are not actually working on the splitstring array itself inside the for loop. So you’ll need to save each of those changes to i so that you can then use them for the return statement.

First of all, it would help others and you too to use variable names that describe the information contained in them. You use a variable named i in your for loop, but that is not very descriptive.

Ignoring this fact, after the following line executes, i will contain a sentence word with the first letter capitalized and the remaining part of the word the same as the original letters’ case. The rest of the word should be lowercase.

i = spliti.join("");

There are some other issues you will still need to sort out (like making use of the properly cased word in the final value that gets returned), but for now, you need to focus on fixing the the case of each word’s letters.

I’ve already solved the challenge with the following code below, but i want to understand something, isn’t “i” the same as splitstring[entry](ex: isn’t i = splitstring[0], when the for loop starts?), and if that is the case why splitstring[0] is not keeping the value?

function titleCase(string) {
  let splitstring = string.split(" ");
  for (let i = 0; i < splitstring.length; i++) {
    splitstring[i] = splitstring[i].split("");
    for (let j=0; j < splitstring[i].length; j++) {
      splitstring[i][j] = splitstring[i][j].toLowerCase();  
    }
    splitstring[i][0] = splitstring[i][0].toUpperCase();
    splitstring[i] = splitstring[i].join("");
  }
  string = splitstring.join(" ");
  return string;
}

you overwrite it here, and then overwrite it again here:

what value should it keep?

also, i is just a number, it’s not equal to splitstring[entry]

Which piece of code are you referring to? the last one is accepted as a solution, and i am having the problem with the first one.

that doesn’t work in the same way that this doesn’t work:

let arr = [0,1,2,3]
let a = arr[1];
a = a + 1;
console.log(arr); // [0,1,2,3]

I think you are making this a lot more complicated than it needs to be. While your solution may work, to be blunt, it is not pretty to look at. And it seems that even you can’t make complete sense of it since you are still asking questions about it :slight_smile:

You only need one for loop here. And I agree with @RandellDawson, using better variable names may help you create a simpler algorithm. Also, there is nothing wrong with storing results in a temporary data structure to be used later.

for the following code:

let arr = [0, 1, 2, 3];
for (let number of arr) {
   console.log(number);
   number = "CHANGE";
   console.log(number);
}
console.log(arr);

result looks like that:

0
CHANGE
1
CHANGE
2
CHANGE
3
CHANGE
[ 0, 1, 2, 3 ]
  • examine it a little bit to kinda have an idea of what i trying to understand

number is being set to a copy of each number in arr. The first time through the loop, number is set to 0. But that is completely independent from the first element in arr. So when you make a change to number inside of the for loop you are not making a change to the first element in arr. That is why when you return arr at the end it is still exactly the same.

Do you have a source to what you are saying? because the MDN says(about for...of loop) :

It invokes a custom iteration hook with statements to be executed for the value of each distinct property of the object.

Here is the link: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of

It says it right there. You iterate over the values of the properties, not references to the property values inside the object.

In addition to what @JeremyLT pointed out, haven’t you proved to yourself that the iteration variable is a copy and not a reference to an element in the array with the sample code you posted that shows the array didn’t change?

for the value

not

over the value

for the value

not

for a reference to the location in memory where the value is stored

“over the value” has no meaning in this context.

What do you know about pointers?

I kinda didn’t understand yet what the var in the for (let var of iterable ) is exactly is, does it just a variable that copies the value, or the code inside the for...of loop is applied on the actual element of iterable that var takes value of.

pointers? memory addresses?

Yep. Memory addresses.

A variable always holds a single value.

For primitive variables, such as numbers, the value you are storing is your data.

const myVar = 5;
myVar = 6;
console.log(myVar); // the value was changed

For more complex data, such as arrays and objects, the variable holds the location in memory where the data is stored.

const myArr = [1, 2, 3];
 myArr[0] = 6;
console.log(myArr); // the first entry was changed

In a for...of loop, you iterate over the values stored without having access to the original data.

const myArr = [1, 2, 3];
for (let myVal of myArr) {
    console.log(myVal); // this is just a copy of the stored value
    myVal = 5;
}
console.log(myArr); // nothing was changed

If you instead use a for...in loop, you can actually access the contents of your object instead of just getting copies of the values.

const myArr = [1, 2, 3];
for (const myIdx in myArr) {
    console.log(myIdx); // this is 'where to find' a stored value
    myArr[myIdx] = 5;
}
console.log(myArr); // everything was changed

Since arrays are like objects in JavaScript, this all applies equally to arrays and objects. (You even use bracket notation to access the contents of both in a for...in loop.)

1 Like

So in the example of an object (ie: key:value) the for...of loop has access to the values but doesn’t change the actual value associated with the key, but a for...in loop has access to the key and can change the value associated with the key?

I’d say that in a for...of loop you have access to a [shallow] copy of the value.