0

I am doing some JavaScript coding practice, and I wanna copy the Graph

/**
 * // Definition for a Node.
 * function Node(val, neighbors) {
 *    this.val = val === undefined ? 0 : val;
 *    this.neighbors = neighbors === undefined ? [] : neighbors;
 * };
 */

/**
 * @param {Node} node
 * @return {Node}
 */
var cloneGraph = function(node) {
    
    visited = {};
    return recursion(node);
    
    function recursion(node){
        
        if (!node) return null;
        if (visited[node.val]) return visited[node.val];
        
        // clone node and clone edge
        // **I forgot the let, var, const variable declaration here**
        root = new Node(node.val);
        visited[root.val] = root;
        
        if (!node.neighbors) return root;
        for (let i = 0; i < node.neighbors.length; i++) {
            root.neighbors.push(recursion(node.neighbors[i]));
        }
        return root;
    }
};

Here is my code. I forgot to add the variable declaration const, let, var when initialize the new Node. However, seems like the reference is not correct here.

Error : You must return the copy of the given node as a reference to the cloned graph..

Can any one help me understand, why const the var declaration matters here ? For this coding, var, let, const can pass, however, var says to be global, const and let seems like to be block level right ? Thanks.

However, when use d and c blow, we can get the same output as object.

    d = new Node(node.val)
    console.log(d)
    
    const c = new Node(node.val)
    console.log(c)
Jaden
  • 192
  • 4
  • 15
  • 1
    https://www.freecodecamp.org/news/var-let-and-const-whats-the-difference/#:~:text=var%20declarations%20are%20globally%20scoped%20or%20function%20scoped%20while%20let,be%20updated%20nor%20re%2Ddeclared. Refer this – robdev91 Nov 03 '20 at 01:23
  • Thanks, Stefan. But if we do not use the declaration, we assume the variable as the global right ? for this question, I tested the const, var and let , all can pass the question! – Jaden Nov 03 '20 at 01:29
  • 1
    Does this answer your question? [How do JavaScript closures work?](https://stackoverflow.com/questions/111102/how-do-javascript-closures-work) - Your issue is with the closure. Without using var, const, let the variable is used _for each iteration_ of the recursion. – Randy Casburn Nov 03 '20 at 01:33
  • There, `scope` means `accessible`, not object life-cycle. And yes - it will override the global variable if you don't use var/let/const in front of variable declaration. – robdev91 Nov 03 '20 at 01:34
  • 1
    In many contexts, it doesn't matter a whether you use *const*, *let* or *var*. Both *const* and *let* are block scoped, but that doesn't stop them being use for globals. – RobG Nov 03 '20 at 01:53
  • 1
    I much prefer *let* for objects as *const* is not semantic to use for something that can be modified, i.e. isn't a constant. – RobG Nov 03 '20 at 01:57

1 Answers1

1

Because root has been declare as global variable and be changed in every recursive loop, in this line: root.neighbors.push(recursion(node.neighbors[i])); root will not be the current node that in current loop, but the last reference it has been assigned to.

Let demonstrate it by an simple graph:

const oldGraph = [{
  val: 1,
  neighbors: [{
    val: 2
  }, {
    val: 3
  }]
}];

So run cloneGraph(oldGraph[0]), after value 2 done return after check !node.neighbors, recursion back to the line root.neighbors.push(recursion(node.neighbors[i]));. Now root is the node 2 because it has been assigned to new node val 2 in the second recursion, not the root as node 1 you expected.

The variable declaration with var, let, const helps in this case, because they keep the root scope inside current recursion, each iteration will create a new root, not changed any other references.

Test here:

function Node(node) {
  this.val = node.val;
  this.neighbors = [];
}

var cloneGraph = function(node) {
    
    visited = {};
    return recursion(node);
    
    function recursion(node){
        
        if (!node) return null;
        if (visited[node.val]) return visited[node.val];
        
        // clone node and clone edge
        // **I forgot the let, var, const variable declaration here**
        let root = new Node(node);
        visited[root.val] = root;
        
        if (!node.neighbors) return root;
        for (let i = 0; i < node.neighbors.length; i++) {
            root.neighbors.push(recursion(node.neighbors[i]));
        }
        return root;
    }
};

oldGraph = [{
  val: 1,
  neighbors: [{
    val: 2
  }, {
    val: 3
  }]
}];

console.log(cloneGraph(oldGraph[0]));
thanhdx
  • 608
  • 4
  • 16