DEV Community

Cover image for I Tried to Rebuild Array.pop()... Then JavaScript Humbled Me( Learning journal #2-Reference)
Mahin Ahmed
Mahin Ahmed

Posted on

I Tried to Rebuild Array.pop()... Then JavaScript Humbled Me( Learning journal #2-Reference)

It's been 12 days since I started learning JavaScript and it made me a bit annoyed already 😅. I learned about array after completing iteration and loops. So I thought of a little challenge; Why not try to reverse engineer some of array's built-in methods?

I started with reverse engineering array.push() method. My thought process was:

  1. we need to get the max index of the array
  2. we need to add 1 with the max index to get new max index
  3. then we declare a variable with the new max index
  4. then we put a value inside that variable which is then stored to the array Thought of this way because non-existing index returns undefined, so variable not declared or emty value

So basically I was trying to get the last index of an array and then adding another index and assigning a value to it.

// push method

let array = [1,  2,  3,  4,  5];
//    Index: 0,  1,  2,  3,  4

function addElementToArray(arrayName, elementName){
  // const arrayMaxIndex = arrayName.length - 1; 
  // const newMaxIndex = arrayMaxIndex + 1
  // Those lines were unneccessary
  const newMaxIndex = arrayName.length
  arrayName[newMaxIndex] = elementName;
}
Enter fullscreen mode Exit fullscreen mode

I was confident that I can do some more. So I immediately tried to reverse engineer the array.pop() method. And this is where I literary sucked. I thought it this way:

  1. we will create a new array
  2. we will run loop and add the elements of our initial array here
  3. but we will add until the last index, that's it

Visual Diagram of operation-flow
So I began with the following code:

function removeElementFromArray(arrayName){
  let postArray = [];

  for (let i = 0; i < array.length - 1; i++){
  let iniArrayElement = array[i];
  postArray.push(iniArrayElement);
  }
  arrayName = postArray ; 
}
Enter fullscreen mode Exit fullscreen mode

This code was working as expected. It declares an empty array (local scope) inside our function, reads all the elements of our arrayName and adds element one-by-one until the last index. Then it simply assigns the new completed array to our main array, right? No, it doesn't. I was confused cause when i tried console.log(arrayName) after the line arrayName = postArray ;, it was working. But when i tried console.log(array)[array = [1,2,3,4,5]], it gives 1,2,3,4,5 not 1,2,3,4!!

I was really frustrated because I was telling JavaScript to copy all the elements of postArray and assign it to arrayName which refers our main array but JavaScript was kinda betraying me. It was changing the value inside the function but not in the global array. JavaScript wasn't wrong at all! It was I who misinterpreted concepts.

Then I did some research and realized my mistake. JavaScript values are generally grouped into Primitive and Object. When we use = or assignment operator in a variable:

  • If it is Primitive data-type, then JavaScript simply copies the content of the right side variable/content and stores those data in a memory block and assigns the memory address to the variable. So when we write let num = 2;, javaScript does:

Flow of primitive
So even if we do:

let x = 5;
let y = x;

y = 10;

console.log(x); // 5
console.log(y); // 10
Enter fullscreen mode Exit fullscreen mode

only y changes, because '=' in primitive copies the whole content and assigns it to a new memory block and gives the memory address to the variable.

  • If it is an Object-type, then JavaScript doesn't copy the object itself. Instead, it copies the reference to that object. For example:
let arr1 = [5,6,7];
let arr2 = arr1;
Enter fullscreen mode Exit fullscreen mode

Looks like:

Memory pointer
So if we do:

arr2.push(8);
console.log(arr1) // [5,6,7,8]
console.log(arr2) // [5,6,7,8]
Enter fullscreen mode Exit fullscreen mode

So push() is actually changing the memory block content which arr2 is pointing at, but arr1 is also pointing at the same address. So as both 'share' the same memory block content, the changes apply to both. But if we do arr2 = [1,2,3] then the engine will actually create a new memory block and assigns its address to arr2 and the changes will be only applicable to arr2.

That is why when i tried arrayName = postArray, I was actually telling JavaScript:

Hey, please change the arrayName reference so it points to postArray address. And the fun fact is that when we sayremoveElementFromArray(array) then JavaScript just tells the engine to make the local variable arrayName point to the same address where the data of global variable array points. We can see this in action:

function test(arrayname){
  arrayname.push('hah');
  console.log(arrayname);
}

test(array); // [ 1, 2, 3, 4, 5, 'hah' ]
console.log(array); // [ 1, 2, 3, 4, 5, 'hah' ]
Enter fullscreen mode Exit fullscreen mode

So the changes applies to both cause both is pointing at the same memory address reference. So what was wrong with our function removeElementFromArray? Because I was telling JavaScript to change the memory address of arrayName to the address which refers to postArray. So I was not updating my array at all. That is why the changes was visible inside the function as I was doing console.log(arrayName) but was not visible as I was doing console.log(array). Built-in methods like push() actually modifies the content, but = actually changes what the variable is referring.

Lesson: I have to make sure I keep the concent of reference in mind while working with data.
The biggest realization:

= NEVER modifies an object.

= NEVER modifies a primitive.

= NEVER modifies ANY value.

It ONLY changes what the variable on the LEFT refers to.

How I then approaches the problem?
A function cannot change which object the caller's variable refers to, but it can mutate the object that both the caller and the parameter currently reference.
I understood that I can't reliably change the global array permanently, rather I can return the changed array and do the rest of the operations with this. But I went deeper and learned about objects also. And then I realized 'every list is essentially an object which has a built-in property called length'.

Array

0 : 10
1 : 20
2 : 30
3 : 40
length : 4

Important:

length is just another property of the array.

So I thought of why not access the property length and change it to currentLength - 1? And I did it.

function removeElementFromArray(arrayName){
  arrayName.length = arrayName.length - 1
  return arrayName; // returning Just for testing
}
Enter fullscreen mode Exit fullscreen mode

In conclusion, JavaScript isn't strange. I was the one who didn't understand how it works. I love solving this types of problems. Facing such problems always makes me learn something new or understand the system better. And I love these sufferings 🙃.

Thanks for taking the time to read this. I really appreciate you cause as a learner, I need people to help me go in the right direction and learn properly. My assumptions might be wrong, or maybe I have explained something in a wrong way or used wrong words. Hoping that you will provide some helpful feedback. And please let me know what mistakes I am still doing.

Top comments (0)