Kodekan
Kodekan

Reputation: 1601

JavaScript Use a string value as reference to an object (not using eval())

I create a bunch of Objects (Nodes) with properties like "name", "type", "positionX", "positionY", etc. They also have an array "connections" which starts empty. When creating an Object, I also store it in an Array objectList so I can easily traverse them in loops.

//Pseudo-Object
function Node (n,t,x,y) {
    this.name = n;
    this.type = t;
    this.connections = new Array();
    this.positionX = 0;
    this.positionY = 0;
    tempArrayPosition = nodeList.length;
    nodeList[tempArrayPosition] = this;
}

//Create node list
var nodeList = new Array();

//Create some nodes
var node1 = new Node("node.foo", "io", 40, 60);
var node2 = new Node("node.bar", "fw", 10, 10);
var node3 = new node("node.narf", "mcu", 20, 100);

Traversing through the nodeList Array works ok. I can for example use this code to display, how many connections one node Object has:

//Create some connections (will later be done by a method of Node)
node2.connections[node2.connections.length] = "node1";
node2.connections[node2.connections.length] = "node3";
node3.connections[node3.connections.length] = "node2";

console.log("Show number of connections between nodes:");
for (var i = nodeList.length - 1; i >= 0; i--) {
    console.log("Node " + nodeList[i].name + " has " + nodeList[i].connections.length + " connections to other nodes.");
};

Now the problem starts when I want to display the connections in detail. The .connections array consists of strings of variable/object names. But I can't seem to use them to access those objects.

I expand the loop like this:

console.log("Show number of connections between nodes:");
for (var i = nodeList.length - 1; i >= 0; i--) {
    console.log("Node " + nodeList[i].name + " has " + nodeList[i].connections.length + " connections to other nodes.");
    if (nodeList[i].connections.length > 0) {
        for (var j = nodeList[i].connections.length - 1; j >= 0; j--) {
            var tempObjectName = nodeList[i].connections[j];
            console.log(nodeList[i].name    + " - " + tempObjectName.name);
        }
    }
};

It returns "undefined" - because clearly it doesn't see "node1", etc. as object references but strings. I know that I could use

var tempObjectName = eval(nodeList[i].connections[j]);

But even with my very little experience in JS I've seen "eval() is evil, don't use it" a dozen times...

So my questions are:

Thank you for your time.

Upvotes: 0

Views: 127

Answers (2)

user1636522
user1636522

Reputation:

You should store the object itself instead of its name :

node2.connections.push(node1);

If you don't like this suggestion, try this :

var tempObjectName = window[nodeList[i].connections[j]];

Will work if node1, node2, nodeN are declared in the global scope, which is a dirty practice.

Upvotes: 2

Ashish Kumar
Ashish Kumar

Reputation: 3039

your tempObjectName is a string, not an object. check typeof tempObjectName in your code. If you will print tempObjectName, it will give you the desired result.

for (var i = nodeList.length - 1; i >= 0; i--) {
    console.log("Node " + nodeList[i].name + " has " + nodeList[i].connections.length + " connections to other nodes.");
    if (nodeList[i].connections.length > 0) {
        for (var j = nodeList[i].connections.length - 1; j >= 0; j--) {
            var tempObjectName = nodeList[i].connections[j];
            console.log(typeof tempObjectName);
            console.log(nodeList[i].name    + " - " + tempObjectName);
        }
    }
};

here is the jsFiddle: http://jsfiddle.net/ashishanexpert/y9ZEW/

Upvotes: 1

Related Questions