'Output on Narcissistic Numbers keeps being undefined

I am trying to solve a kata from Codewars but I bumped into a wall. I'll leave the instructions down below and my code. If anyone can guide me through the answer or simply what is wrong with my code I will kindly appreciate it.

Instructions

A Narcissistic Number is a positive number which is the sum of its own digits, each raised to the power of the number of digits in a given base. In this Kata, we will restrict ourselves to decimal (base 10).

For example, take 153 (3 digits), which is narcisstic:

1^3 + 5^3 + 3^3 = 1 + 125 + 27 = 153

and 1652 (4 digits), which isn't:

1^4 + 6^4 + 5^4 + 2^4 = 1 + 1296 + 625 + 16 = 1938

My Code

function narcissistic(value) {
  let sum = 0;
  for(let i = 0; i < value.length; i++){
    sum += Math.pow(value[i], 3);
    
    if(sum == value){
      return true;
    } 
    return false;
  }
}


Solution 1:[1]

I'd personally suggest:

// we accept a numeric representation, either 123 or "123":
const isNarcissistic = (number) => {

  // here we set the passed-in number to a String,
  // and then split that string to an Array of
  // single-character number-strings;
  // 123 -> "123" -> ["1","2","3"],
  // "123" -> "123" -> ["1","2","3"]:
  let numbers = number.toString().split(''),
    // we find the length of the Array (the
    // amount of characters in the original
    // passed-in number to determine the power;
    // 123 = length of 3:
    power = numbers.length,
    // we use Array.prototype.reduce() to
    // calculate the sum of the values raised
    // to the power we found earlier;
    // acc: the accumulator,
    // curr: the current array-element of the
    // Array we're iterating over:
    res = numbers.reduce((acc, curr) => {
      // here we add the current-value of the
      // accumulator to the result of raising
      // the current-value (passed to parseInt()
      // with a radix of 10) to the power we
      // found earlier:
      return acc + Math.pow(parseInt(curr, 10), power);
      // setting the accumulator to an initial value
      // of zero:
    }, 0)
  // here we return whether the final result is equal to
  // the number passed in, whether as a number or
  // as a String, using parseInt() with a radix of
  // 10, to get a base-10 number:
  return res === parseInt(number, 10);
}

// this is a useage demonstration; and largely irrelevant to the posted problem,
// however: we use document.querySelectorAll() to retrieve all elements in the
// document that match the supplied CSS selector, this returns a NodeList, which
// we then pass to NodeList.prototype.forEach():
document.querySelectorAll('li').forEach(
  // here we use an Arrow function, to pass the current element-node of the
  // NodeList over which we're iterating to the single-line function-body;
  // in that function body we access the classList of the element,
  // and use the toggle method passing in the name of the class to toggle,
  // and call our function (isNarcissistic) to determine whether the
  // textContent of the current element is narcissistic; if the function returns
  // (Boolean) true the class-name is added (or kept), if the function returns
  // (Boolean) false the class-name is not added (or it's removed):
  (el) => el.classList.toggle('isNarcissistic', isNarcissistic(el.textContent))
)
*,
 ::before,
::after {
  box-sizing: border-box;
  font: normal 1rem / 1.5 sans-serif;
  margin: 0;
  padding: 0;
}

ul {
  display: flex;
  justify-content: space-around;
  gap: 1em;
  width: 90vw;
  margin-inline: auto;
  margin-block: 1em;
}

li {
  list-style-type: none;
  border: 2px solid transparent;
  flex-grow: 1;
}

.isNarcissistic {
  border-color: lime;
}
<ul>
  <li>153</li>
  <li>370</li>
  <li>406</li>
  <li>407</li>
  <li>1634</li>
</ul>

JS Fiddle demo.

The problems with your existing solution:

// you use the 'value' argument within your
// function without checking that it's a
// Number or String (if you're the only one
// using it, that's fine, but usually unsafe):
function narcissistic(value) {
  let sum = 0;

  // your for initialises i as zero, which is fine
  // as it's an iterator, but you then test that
  // i is less than the length of 'value', which
  // if 'value' is a Number will evaluate to false
  // because a Number has no 'length' property,
  // if it evaluates to false the loop will never
  // be entered (and the function will return false)
  // if 'value' is a String, the loop will be entered:
  for(let i = 0; i < value.length; i++){

    // here we add the result of raising the
    // character held at the 'ith' position
    // of the String, and it will be raised
    // to the power of 3 (regardless of the
    // number of characters in the String, so
    // any number of less, or more, than 3
    // characters will not behave as expected:
    sum += Math.pow(value[i], 3);

    // here you use '==' which will return
    // true for "123" == 123; the second
    // argument will be coerced to the same
    // type of variable as the first, whether
    // from String to Number, or Number to String
    // (this can be useful if you know what
    // you're doing, but usually '===' is preferred
    // since that checks that the two arguments are
    // exactly equal, both are Numbers, or Strings,
    // and that String or Number has the same value):
    if(sum == value){
      return true;
    } 
    return false;
  }
}

References:

Solution 2:[2]

There are 3 issues:

  1. value is allowed to be a Number and not forced to be a String which would cause .length and [i] to be undefined. Which prevents the for loop from even running
  2. Math.pow is always called with an exponent of 3 which is not dynamic based on the input as the spec requires
  3. the return statement is inside the for loop. This means it will return true/false on the first iteration

Fixing these 3 would look something like this (I did not test this code yet)

function narcissistic(value) {
  // always treat it as text for .length and [index] accessors
  // if the number started with a `0` it would have to be passed in as a string regardless as `Number` does not support that...
  value = value.toString();
  // sum is a number as we add to it
  let sum = 0;
  // since value is a string `.length` will give us the digits
  const digits = value.length;

  for(let i = 0; i < digits; i++) {
    // Math.pow() supports number strings for the first argument
    // note that floating point numbers will break this as `.` is invalid
    sum += Math.pow(value[i], digits);
  }

  // == does a loose comparison so 1567 == '1567' is true
  return sum == value;
}

Solution 3:[3]

You are doing it completely wrong. You cannot iterate over a number like that because it is not a string hence value[i] will always return undefined. Here is the correct way

/*Getting number of digits*/ 
function getlength(number) {
    return number.toString().length;
}
function narcissistic(value) {
let power = getlength(value);
  let sum = 0;
  let temp_val= new Number(value); // Creating a new copy of the value at different location so they do'nt reference to same number
  while(temp_val>0){ // Getting digits from right to left
     let digit = temp_val%10; 
    sum += Math.pow(digit, power);
    temp_val= Math.floor(temp_val/10); // Taking only integer values
  }
    if(sum == value){
      return true;
    } 
    return false;
}
let value = 153
console.log(narcissistic(value));

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2
Solution 3