I'm trying to create an array of objects with a "Node" class constructor. Each Node should have an array containing neighbouring nodes. When I use a for loop to iterate through each Node to add neighbours, it triggers the class method, but the Node object fails to update.
Here's a contrived/simplified version of what I'm doing:
export default class Node {
neighbours: Node[];
addNeighbours: (thisNode: Node) => void;
constructor() {
this.neighbours = [];
this.addNeighbours = function (thisNode: Node) {
thisNode.neighbours = []
this.neighbours.push(thisNode)
console.log(this.neighbours.length); // returns 1. So this is being triggered and appears to be working.
}
}
}
// Create an array to represent the 2D grid.
export function createArrayOfNodes(): Node[][] {
let returnGrid: Node[][] = [
[new Node(), new Node(), new Node()],
[new Node(), new Node(), new Node()],
[new Node(), new Node(), new Node()],
]
// add neighbours to each Node
for (let i = 0; i < returnGrid.length; i ) {
for (let j = 0; j < returnGrid.length; j ) {
const newJ = j 1 === returnGrid.length ? 0 : j 1
returnGrid[i][j].addNeighbours(returnGrid[i][newJ]); // This fails to add a neighbour
// returnGrid[i][j].addNeighbours(new Node()); // This adds a neighbour OK
}
}
// returnGrid[0][0].addNeighbours(returnGrid[0][1]); // This adds a neighbour OK
return returnGrid;
}
console.log(createArrayOfNodes) // Returns an array of Nodes, but they don't have any Nodes in their neighbour properties.
As per the commented out code, I can update the neighbours
property if it's outside the for
loop. If I'm inside the for
loop I can update the neighbours
property if I create a new Node, but not if I try to add a Node from the returnGrid
. Can anyone please explain this?
CodePudding user response:
Seems the following line made your code not work. Commented it out all works fine.
thisNode.neighbours = [];
Node should look like below
export default class Node {
neighbours: Node[];
addNeighbours: (thisNode: Node) => void;
constructor() {
this.neighbours = [];
this.addNeighbours = function (thisNode: Node) {
this.neighbours.push(thisNode);
};
}
}
Actually, you could have defined the addNeighbours
outside the constructor.
export default class Node {
neighbours: Node[];
constructor() {
this.neighbours = [];
}
addNeighbours = function (thisNode: Node) {
this.neighbours.push(thisNode);
};
}
Working example,
CodePudding user response:
Everytime you call the addNeighbours
method you reassign the neighbours
array of the passed Node
. This will effectively reset the neighbours
array of that passed Node
.
Remove the thisNode.neighbours = []
line.
class Node {
neighbours = [];
addNeighbours(thisNode) {
this.neighbours.push(thisNode)
}
}
// Create an array to represent the 2D grid.
function createArrayOfNodes() {
let returnGrid = [
[new Node(), new Node(), new Node()],
[new Node(), new Node(), new Node()],
[new Node(), new Node(), new Node()],
]
// add neighbours to each Node
for (let i = 0; i < returnGrid.length; i ) {
for (let j = 0; j < returnGrid.length; j ) {
const newJ = j 1 === returnGrid.length ? 0 : j 1
returnGrid[i][j].addNeighbours(returnGrid[i][newJ]);
}
}
return returnGrid;
}
console.log(createArrayOfNodes());
Sidenote: I noticed how you declared your properties and methods on your Node
class. You're allowed to assign properties and methods that every instance should inherit inside of the class
scope, instead of the constructor
.
The constructor
can be used to assert logic and process arguments when instantiating classes.
export default class Node {
neighbours: Node[] = [];
addNeighbours(thisNode: Node): void {
this.neighbours.push(thisNode)
}
}