Vincent Tang
Vincent Tang

Reputation: 4170

Javascript : typeerror not a function

I have a snippet of code that updates records in a json object representing a musical album collection. The function written here updates the records given an album ID, a property ("tracks"), and a value ("albumName")

The error I get below is:

"message": "Uncaught TypeError: collection[id][prop].push is not a function",

    var collection = {
        "2548": {
          "album": "Slippery When Wet",
          "artist": "Bon Jovi",
          "tracks": [ 
            "Let It Rock", 
            "You Give Love a Bad Name" 
          ]
        },
        "2468": {
          "album": "1999",
          "artist": "Prince",
          "tracks": [ 
            "1999", 
            "Little Red Corvette" 
          ]
        },
        "1245": {
          "artist": "Robert Palmer",
          "tracks": [ ]
        },
        "5439": {
          "album": "ABBA Gold"
        }
    };
    
    // Only change code below this line
    function updateRecords(id, prop, value) {
      if(!value){
        delete collection[id][prop];
        return collection;
      }
      if(prop === "tracks"){
        if(!collection[id].hasOwnProperty('tracks')){
          collection[id].tracks="";
        }
        if(value){
          collection[id][prop].push(value);
        }
      } else {
        collection[id][prop] = value;
      }
    
      return collection;
    }
    
    updateRecords(5439, "tracks", "Take a Chance on Me");

Some other test case scenarios

enter image description here

Upvotes: 0

Views: 379

Answers (4)

Scott Marcus
Scott Marcus

Reputation: 65855

A simple log of id and prop in that section shows that id = 5439 and prop = tracks and the object with an id of 5439 doesn't have a tracks property. So, collection[id][prop] is returning undefined and undefined does not have a push method.

The solution would be to test for the existence of the tracks property and to create it if it doesn't exist.

var collection = {
        "2548": {
          "album": "Slippery When Wet",
          "artist": "Bon Jovi",
          "tracks": [ 
            "Let It Rock", 
            "You Give Love a Bad Name" 
          ]
        },
        "2468": {
          "album": "1999",
          "artist": "Prince",
          "tracks": [ 
            "1999", 
            "Little Red Corvette" 
          ]
        },
        "1245": {
          "artist": "Robert Palmer",
          "tracks": [ ]
        },
        "5439": {
          "album": "ABBA Gold"
        }
    };
    
    // Only change code below this line
    function updateRecords(id, prop, value) {
      if(!value){
        delete collection[id][prop];
        return collection;
      }
      if(prop === "tracks"){
        if(!collection[id].hasOwnProperty('tracks')){
          collection[id].tracks="";
        }
        if(value){         
          // If the property doesn't exist...
          if(!collection[id][prop]){
            // Create it and initialize it to an empty array
            collection[id][prop] = [];
          }
          // Now, it's safe to push the new value into the array
          collection[id][prop].push(value);
          
          console.log(collection[id]);  // <-- Test
        }
      } else {
        collection[id][prop] = value;
      }
    
      return collection;
    }
    
    updateRecords(5439, "tracks", "Take a Chance on Me");

Upvotes: 1

Varinder
Varinder

Reputation: 2664

You may want to initialize an empty array for an item id that is not found in the collection like so:

var collection = {
    "2548": {
      "album": "Slippery When Wet",
      "artist": "Bon Jovi",
      "tracks": [ 
        "Let It Rock", 
        "You Give Love a Bad Name" 
      ]
    },
    "2468": {
      "album": "1999",
      "artist": "Prince",
      "tracks": [ 
        "1999", 
        "Little Red Corvette" 
      ]
    },
    "1245": {
      "artist": "Robert Palmer",
      "tracks": [ ]
    },
    "5439": {
      "album": "ABBA Gold"
    }
};

// Only change code below this line
function updateRecords(id, prop, value) {
  if(!value){
    delete collection[id][prop];
    return collection;
  }
  if(prop === "tracks"){
    if(!collection[id].hasOwnProperty('tracks')){
      collection[id].tracks=[]; // notice new array initialization
    }
    if(value){
      collection[id][prop].push(value);
    }
  } else {
    collection[id][prop] = value;
  }

  return collection;
}

updateRecords(5439, "tracks", "Take a Chance on Me");

Upvotes: 1

Pablo
Pablo

Reputation: 6058

+1 for providing a working sample to reproduce the issue.

The issue is with the line collection[id].tracks="" it should be collection[id].tracks=[]

See the updated example below:

var collection = {
        "2548": {
          "album": "Slippery When Wet",
          "artist": "Bon Jovi",
          "tracks": [ 
            "Let It Rock", 
            "You Give Love a Bad Name" 
          ]
        },
        "2468": {
          "album": "1999",
          "artist": "Prince",
          "tracks": [ 
            "1999", 
            "Little Red Corvette" 
          ]
        },
        "1245": {
          "artist": "Robert Palmer",
          "tracks": [ ]
        },
        "5439": {
          "album": "ABBA Gold"
        }
    };
    
    // Only change code below this line
    function updateRecords(id, prop, value) {
      if(!value){
        delete collection[id][prop];
        return collection;
      }
      if(prop === "tracks"){
        if(!collection[id].hasOwnProperty('tracks')){
          collection[id].tracks=[];
        }
        if(value){
          collection[id][prop].push(value);
        }
      } else {
        collection[id][prop] = value;
      }
    
      return collection;
    }
    
    updateRecords(5439, "tracks", "Take a Chance on Me");
    
    console.log(collection[5439])

Upvotes: 3

Kusuma
Kusuma

Reputation: 266

.push is a function of Array object. However, you are using it on a String. You need to initialize it to an Array instead of String

if(!collection[id].hasOwnProperty('tracks')){
      collection[id].tracks=[];
    }

Upvotes: 1

Related Questions