0

I need some help debugging a problem with a simple graph (data structure, not a chart). I can insert a node, as well as create a path to the next nodes fine; that's not a problem. The problem is when I call returnGraph the node at the first index is returned as [object Object], but all the other nodes are returned as they should be. This is being wrriten with AngularJS by the way.

So I looked for a solution and I read in a few places that this has something to do with either the object's built in string method or a conflict between javascript-objects and json-objects. Unfortunately I'm a little lost since I'm not too familiar with Javascript internals.

First off, here is an example JSON object I am using:

//JSON object waiting to be passed to Node()
obj1 = {
    id: 6111,
    name: "Node1",
    stats: {
        "speed": 4
    },
    ranks: 5,
    prereq: 0
}

Here is the rest of the code:

//Pass data from the JSON object through the constructor to create a node
function Node(data){

    this.name = data.name;
    this.stats = data.stats;
    this.maxRank = data.ranks;
    this.rank = 0;
}

//Return node name
Node.prototype.returnName = function(){
    return this.name;
}

//Increase node rank
Node.prototype.increaseRank = function(){
    if (this.rank < this.maxRank){
        this.rank += 1;
    }
    console.log(this.rank);
}



//Graph object
function Graph(){
    this.edges = []
}

Graph.prototype.returnNeighbors = function(node){
    return this.edges[node];
}

Graph.prototype.addNeighbor = function(node1, node2, node3, node4){

    // Prints out node1 as an object
    console.log(node1); // Prints out node1 as an object
    if (node1 == null){
        console.log("something went terribly wrong!");
    }
    else if (node1 != null && node2 == null && node3 == null && node4 == null) {
        this.edges.push({[node1]: []});
    }
    else if (node4 == null){
        this.edges.push({[node1]:[node2, node3]})
    }
    else{
        this.edges.push({[node1]: [node2, node3, node4]})
    }
}

Graph.prototype.returnGraph = function(){
    return JSON.stringify(this.edges, null, 2);
}


// create a node for each JSON object
$scope.node1 = new Node(obj1);
$scope.node2 = new Node(obj2);
$scope.node3 = new Node(obj3);
$scope.node4 = new Node(obj4);


// create graph
var g = new Graph();
g.addNeighbor($scope.node1, $scope.node2, $scope.node3, $scope.node4);
$scope.g = g;

console.log(g.returnGraph());

This is where the problem lies and is what the above statement prints out. Keep in mind this is the Graph:

[
  {
    "[object Object]": [
      {
        "name": "Node2",
        "stats": {
          "speed": 4
        },
        "maxRank": 5,
        "rank": 0
      },
      {
        "name": "Node3",
        "stats": {
          "attack": 4
        },
        "maxRank": 5,
        "rank": 0
      },
      {
        "name": "Node4",
        "stats": {
          "block": 4
        },
        "maxRank": 5,
        "rank": 0
      }
    ]
  }
]

I've tried using JSON.parse() but that wasn't working. I also converted the first node into a string with JSON.stringify() and then directly input that string data instead of the actual object, which got me closer , yet it was full of escapes (\\,\t,\n). Using regex didn't help clean it up either.

So is there a better way to solve this [object Object] problem? I looked through a lot of answers but could not find a solution. Thanks for any help!

5
  • I suspect your problem is in the code that looks like this: this.edges.push({[node1]: []}); You're pushing a new key/value pair into the object but you're giving it a key name of whatever is contained in node1. However, node1 isn't a string, it's an object so Javascript is converting the object to a string which gives you [object Object] Commented Aug 23, 2016 at 22:28
  • So my question to you: what key name do you really intend to use? Perhaps you meant to type something like node1.name? Commented Aug 23, 2016 at 22:28
  • Yes, I currently have it inside the returnGraph() method, returning the graph as a JSON object. I also tried it outside of the method, where I instantiate the nodes. I explained it in the last paragraph in case you missed it; The issue with this is it returns the exact string representation of that node, which is filled with escapes :( Commented Aug 23, 2016 at 22:29
  • What key name are you expecting instead of [object Object]? Commented Aug 23, 2016 at 22:30
  • @Dr.Cool Okay I think I think I see where this is going. I expect to see the node1.name. Commented Aug 23, 2016 at 22:33

1 Answer 1

1

I suggest that you update your addNeighbor() function like this:

Graph.prototype.addNeighbor = function(node1, node2, node3, node4){
    // Prints out node1 as an object
    console.log(node1); // Prints out node1 as an object
    if (node1 == null){
        console.log("something went terribly wrong!");
    }
    else if (node1 != null && node2 == null && node3 == null && node4 == null) {
        this.edges.push({[node1.name]: []});
    }
    else if (node4 == null){
        this.edges.push({[node1.name]:[node2, node3]})
    }
    else{
        this.edges.push({[node1.name]: [node2, node3, node4]})
    }
}

You're pushing a new object into an existing object. The new object has a key defined as node1.name which will give you an actual string value for the key name. Your code was using node1. Javascript will realize that node1 isn't a string so it will automatically convert the object to a string which is where you're getting [object Object] from.

Sign up to request clarification or add additional context in comments.

8 Comments

So your saying to take node1 out of the brackets [ ]? I actually did try this, and the value literally becomes node1 and not node "Node1", which is the value of node1.name, the value I was expecting.
Okay wait, read that wrong. Let me try what you are saying! Thanks
Leave the brackets there so that Javascript uses the node1.name as the key. Otherwise, it will give you an error as it gets confused by the period in the dot notation.
Here's a working codepen. Click the console button at the bottom to see the result: codepen.io/DrCool/pen/ZONkPW
Awesome, okay this solves most of my issue! I can work with it. However, if I wanted it to display all of the attributes of node1 and not just it's name, how would I approach this?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.