DEV Community

Cover image for About "TypeError: map is not a function" in JavaScript
Reza Lavarian
Reza Lavarian

Posted on • Originally published at decodingweb.dev

About "TypeError: map is not a function" in JavaScript

Update: This post was originally published on my blog decodingweb.dev, where you can read the latest version for a 💯 user experience. ~reza

The error “TypeError: object.map is not a function” occurs when you call the map() method on a non-array object in JavaScript.

A non-array object can be an object literal, a string, a Map object, a Set object, etc.

Let’s see a simple example:

let data = {
    course: 'JavaScript for Beginners', 
    language: 'JavaScript'
}

// This will cause the error
let newData = data.map(item => {
    // do something ...
    return item
})
Enter fullscreen mode Exit fullscreen mode

The above code raises the "TypeError: object. map is not a function" error because the calling object isn't an array - it's an object literal.

The map() method in JavaScript only works on arrays

The map() method is a part of the array prototype, meaning you can only call it on JavaScript arrays. Here's how MDN Web Docs defines it:

Array.prototype.map()
The map() method creates a new array populated with the results of calling a provided function on every element in the calling array.

let data = ['apples', 'bananas', 'oranges', 'grapes']

// This is correct
let newArray = data.map(item => {
// do something here ...
return item
})
Enter fullscreen mode Exit fullscreen mode

How to solve "map is not a function" error in JavaScript

Whenever you encounter this error, inspect the variable calling map() - You can use console.log(data) to do so.

console.log(data)
Enter fullscreen mode Exit fullscreen mode

Before making any change to your code, ensure you're calling map() on the correct data object because you might be calling map() on an object, whereas you intended to refer to an array inside that object!

Here's an example:

// ...

let data = {
    success: true,
    items: [
        {
            course: 'JavaScript for beginners'
        },
        {
            course: 'PHP programming'
        },
        {
            course: 'Learning Python'
        }
    ]
}

console.log(data.items)
Enter fullscreen mode Exit fullscreen mode

If you called the map() method against the main data object, you'd have to change it to data.items instead:

// ...

let newArray = data.items.map(item => {
    // do something here ...
    return item
})
Enter fullscreen mode Exit fullscreen mode

Please note if data contains raw JSON, you should parse it into a valid JavaScript object literal with the help of JSON.parse().

// ...

data = JSON.parse(data)
Enter fullscreen mode Exit fullscreen mode

How to work around "... map is not a function" error when using object literals?

If you have an object literal and want to use it with the map() function, you need to convert your data into an array representation.

There are several ways to do this. Let's explore each with a quick example.

Using Object.keys(): Since the map() function only works with array values, you can create an array from the keys in your object and call map() on the resulting array.

Consequently, you can access the original object data using the key in a bracket notation: data[key].

Let's see how:

// map-object-keys.js

let data = {
    course: 'JavaScript for beginners',
    language: 'JavaScript',
    creator: 'decodingweb.dev'
}

let dataKeys = Object.keys(data)
// dataKeys: ['course', 'language', 'creator']

let newData = dataKeys.map(key => {
    // Get the data from the original object with the bracket notation
    let item = data[key]

    // do something here ...
    return item
})
Enter fullscreen mode Exit fullscreen mode

Using Object.values(): Instead of object keys, you can create an array from the object values too:

// map-object-values.js

let data = {
    course: 'JavaScript for beginners',
    language: 'JavaScript',
    creator: 'decodingweb.dev'
}

let dataKeys = Object.values(data)
// dataKeys: ['JavaScript for beginners, 'JavaScript'', 'decodingweb.dev']

let newData = dataKeys.map(itemValue => {
    // do something here ...
    return itemValue
})
Enter fullscreen mode Exit fullscreen mode

Using Object.entries() method: If you need to access to key/value pair in your map() callback, you can use Object.entries(). This function creates an array consisting of [key, value] arrays:

// map-object-entries.js

let data = {
    course: 'JavaScript for beginners',
    language: 'JavaScript',
    creator: 'decodingweb.dev'
}

let dataKeys = Object.entries(data)
/*
 dataKeys: [
    ['course',   'JavaScript for beginners']
    ['language', 'JavaScript']
    ['creator',  'decodingweb.dev']
]
*/

let newData = dataKeys.map(item => {
    // do something here ...

    console.log(item[0]) // key
    console.log(item[1]) // value

    return  item
})
Enter fullscreen mode Exit fullscreen mode

Add a length property to objects with integer-keyed properties: If you have an object with numerical keys, you can make it map-ready by giving it a length property. After adding the length property, which should contain the number of properties in the object, you can call the map() method manually.

Let's see an example:

// object-to-array.js

let data = {
    0: 'JavaScript',
    1: 'PHP',
    2: 'Python'
}

// Adding the length property
data['length'] = 3

/* 
The data now looks like this: 
{
    length: 3,
    0: 'JavaScript',
    1: 'PHP',
    2: 'Python'
}

*/

// We call the map directly from the Array prototype passing data as the context (this)
let newData = Array.prototype.map.call(data, item => item)
Enter fullscreen mode Exit fullscreen mode

Since map() is a function, we can invoke it via call(). We pass our object as the context (this) to the call as the first argument. The second argument is the callback function, which is eventually passed to the map() method.

If you're using JavaScript Map objects

If you're calling the map() method on a Map object, you'll still get this error.

Luckily, Map objects implement keys(), values(), and entries() methods. Using these methods, you generate arrays based on keys, values, or key/value pairs respectively (just like object literals in the above examples).

//map-on-map-object.js

const map1 = new Map()

map1.set('a', 1)
map1.set('b', 2)
map1.set('c', 3)

// Since Map.prototype.keys() return a Map Iterator object, we use the spread operator to turn it into an array
let mapKeys = [...map1.keys()] // [1, 2, 3]

let newData = mapKeys.map(key => {
    // Do something here ...

    return [key, map1.get(key)]
})

// Create a new Map object with the transformed array
map2 = new Map(newData)
Enter fullscreen mode Exit fullscreen mode

You could also use map1.values() and map1.entries() methods accordingly.

If you're working with a JavaScript Set object, the algorithm is the same.

Adding a check: Array.isArray()

If you want to call the map() method only if the data is an array (without adjusting it), you can put your code inside a conditional statement:

// map-array-if.js

let data = ['JavaScript', 'PHP', 'Python']
let newData = []

if (Array.isArray(data)) {
newData = data.map(item => {
         return item 
       })
}

console.log(newData)
Enter fullscreen mode Exit fullscreen mode

As a result, the map() method will only be called if the respective data object is a JavaScript array.

Wrapping up

Alright, I think that does it! Whenever you encounter this error, first check you're using an array. If the input isn't an array object, before anything, ensure you're referring to the right value. Then, depending on your object (object literal, Map, or Set) transform your data into an array, then call its map() method.

Additionally, you can check if the object is an array, and then, call the map() method against it.

Thanks for reading.


❤️ You might like:

Latest comments (0)