Implement map on a Prototype-why

I have done it in three ways and this is the 4th which is buggy I think but I don’t know what is the cause for adding a ‘NaN’ at the end…?
Thanks in advance

Your code so far


// the global Array
var s = [23, 65, 98, 5];

Array.prototype.myMap = function(callback){
  var newArray = [];
  // Add your code below this line
 

  for (let i in this) {
    newArray.push(callback(this[i]))
  }
  // Add your code above this line
  return newArray;

};

var new_s = s.myMap(function(item){
  return item * 2;
});
console.log(new_s);

Your browser information:

User Agent is: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:65.0) Gecko/20100101 Firefox/65.0.

Link to the challenge:
https://learn.freecodecamp.org/javascript-algorithms-and-data-structures/functional-programming/implement-map-on-a-prototype

By extending the Array prototype, you’re actually adding a new i to every array. You can see that if you change your code to this:

var s = [23, 65, 98, 5];

Array.prototype.myMap = function(callback){
  var newArray = [];
  for (let i in this) {
    newArray.push(i) // this line changed
  }
  return newArray;
};

var new_s = s.myMap(function(item){
  return item * 2;
}); // ["0", "1", "2", "3", "myMap"]

Instead, you could try using the length property to get all the correct indexes.

Incidentally, this kind of thing is one good reason that extending prototypes is usually discouraged in production code: it can lead to unexpected results, especially when used alongside third-party code.

you are right the length is 5
but this for (let i = 0; i < this.length; i++) works fine

Yep, that should work consistently.

Incidentally, if you do want to extend a prototype in production code, you can do it using the Symbol type, which won’t be iterated over when you use for...in, and is globally unique, so it will never lead to unintentional property conflicts:

var POOP = Symbol('poop'); // symbol type

Array.prototype[POOP] = () => '💩';

for (let i in ['a', 'b', 'c']) {
  console.log(i);
} // logs 0, 1, and 2, but not poop

vs.

var POOP = 'poop'; // string type

Array.prototype[POOP] = () => '💩';

for (let i in ['a', 'b', 'c']) {
  console.log(i);
} // logs 0, 1, 2, and poop
1 Like

Really clear and informative explanation :star_struck:
Thanks a lot