Caesar Cipher [The Odin Project-Javascript Exercise] Very new to coding, so please don't bully me.

Implement the legendary caesar cipher:

In cryptography, a Caesar cipher, also known as Caesar's cipher, the shift cipher, Caesar's code or Caesar shift, is one of the simplest and most widely known encryption techniques. It is a type of substitution cipher in which each letter in the plaintext is replaced by a letter some fixed number of positions down the alphabet. For example, with a left shift of 3, D would be replaced by A, E would become B, and so on. The method is named after Julius Caesar, who used it in his private correspondence.

Question: Write a function that takes a string to be encoded and a shift factor and then returns the encoded string:

caesar('A', 1) // simply shifts the letter by 1: returns 'B' the cipher should retain capitalization:

caesar('Hey', 5) // returns 'Mjd; should not shift punctuation:

caesar('Hello, World!', 5) //returns 'Mjqqt, Btwqi!' the shift should wrap around the alphabet:

caesar('Z', 1) // returns 'A' negative numbers should work as well:

caesar('Mjqqt, Btwqi!', -5) // returns 'Hello, World!'

My Solution:

function caesar(string, num) {
let arr = [];
for(let i=0;i&lt;string.length;i++)
  {if(!(/[a-zA-Z]/.test(string[i])))
    {arr[i]=string[i]; continue;}
  let n = string.charCodeAt(i) + num;
  if (string[i] == string[i].toLowerCase()) 
    {if(n&gt;122)  
      {while(n&gt;122)
        {n-=26;}} 
     else  
      {while(n&lt;97)
        {n+=26;}
      }
    }
  else
    {if(n&gt;90)
      {while(n&gt;90)
        {n-=26;}
      } 
     else 
      {while(n&lt;65)
        {n+=26;}
      }
    }
  arr[i]=String.fromCharCode(n);    
  }
console.log(arr.join(''));
}
caesar("Hello, World!", 2);
caesar("Hello, World!", 75);


The code is working perfectly as per requirement, but please help me with a better solution if possible.

And if you do, please use comments to extensively explain the working process, as I'm quite the noob.
Welcome to Code Review, some considerations that can help you to simplify your code:


you have an alphabet of 26 letters, so if the shifting operation is
limited to a 26 characters range you can use the mod operation %26
to determine the final position.
you can have a shift negative operation num (ex. -5), for a 26
set of elements shift this is equal to a positive shift of  Math.abs(26 - Math.abs(num)) , so for 5 the positive shift is 21.


So if you have a c character and you want to obtain the ascii code of the corresponding shifted char of num positions you can obtain it in the following way:

const start = c === c.toLowerCase() ? 'a'.charCodeAt(0) : 'A'.charCodeAt(0);
const diff = c.charCodeAt(0) - start;
const sh = num &gt;= 0 ? diff + num : diff + Math.abs(26 - Math.abs(num));
const code = sh % 26 + start;


The first line returns the ascii code of 'a' or 'A' depending if the char c is lowercase or uppercase called start, the second gives you the difference between c and start, the last two lines calculate the code of the shifted corresponding character.

After your function can be rewritten in the following way:

'use strict';

function caesar(str, num) {
    const arr = [];
    const re = /[a-zA-Z]/;
    for (const c of str) {
        if (re.test(c)) {
            const start = c === c.toLowerCase() ? 'a'.charCodeAt(0) : 'A'.charCodeAt(0);
            const diff = c.charCodeAt(0) - start;
            const sh = num &gt;= 0 ? diff + num : diff + Math.abs(26 - Math.abs(num));
            const code = sh % 26 + start;
            arr.push(String.fromCharCode(code));
        } else { 
            arr.push(c); 
        }
    }

    return arr.join('');
}


I set arr and regex as const and instead of iterate over string using the index, I preferred the for ... of construct.

Note: I'm a javascript beginner too, so every suggestion to improve my code as for the original question is highly appreciated.