0

I have arrays like this:

[ 'markdown', [ 'para', '\'example\'' ] ]

And I have a function that finds recursively the strings inside those arrays:

function traverse(tree, callback) {
  for (var i = 0; i < tree.length; ++i) {
    if (_.isArray(tree[i]) || _.isObject(tree[i])) {
      traverse(tree[i], callback)
    } else {
      callback(tree[i])
    }
  }
}

The problem is, when I perform tasks like replace what's being replaced isn't the actual array but just copies of its nodes. Example:

function replaceQuotes(tree, callback) {

  traverse(tree, function(node) {
    node = node.replace(/'/g, '"')
    console.log(node)
    // outputs: "example"
  })

  callback(null, tree)
}

function showResult(err, tree) {
   console.log(tree)
   // outputs [ 'markdown', [ 'para', '\'example\'' ] ]
}

How can I do it so I can I modify the actual arrays with the transverse function?

(By the way, I'm using the Async Node.js module.)

4
  • 3
    That's because now you're working with the strings in the array, and no longer the array itself, and strings are passed by value only, not copy of a reference of a value etc. Commented Mar 17, 2015 at 13:33
  • Javascript strings are immutable Commented Mar 17, 2015 at 13:35
  • I think you mean 'traverse' Commented Mar 17, 2015 at 13:37
  • @Tom Oh, you're right. Fixed the typo. Commented Mar 17, 2015 at 13:38

1 Answer 1

2

Strings are passed by value - this is why your code behaves the way it does. A good solution is to make your callback return the new value and then modify your traverse slightly:

function tranverse(tree, callback) {
  for (var i = 0; i < tree.length; ++i) {
    if (_.isArray(tree[i]) || _.isObject(tree[i])) {
      tranverse(tree[i], callback)
    } else {
      tree[i] = callback(tree[i]) // changed part
    }
  }
}

You would then use it like this:

function replaceQuotes(tree, callback) {

  tranverse(tree, function(node) {
    return node.replace(/'/g, '"')
  })

  console.log(tree)
  // outputs [ 'markdown', [ 'para', '\'example\'' ] ]

  callback(null, tree)
}
Sign up to request clarification or add additional context in comments.

2 Comments

Hey, it worked. I think I tried something similar in the past but didn't work because I didn't add a return. Why does the return make all the difference?
It's not exactly the return itself, but rather the way you use your callback. In your original code, you modified the node parameter. Since strings are immutable, as already mentioned, any changes to node will only exist inside the callback and won't modify the value in the array itself. This is why you need to modify your traverse to make it do the actual change in the array, while you only use your callback as a way to "transform" the string.

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.