Tic Tac Toe game tree generator minimax
Optimization ideas

Prevent wasteful data conversions

Don't convert from a string to an array. You could do better by simply storing your state as an array instead.

I suppose you chose to use a string since they are easily copied, but arrays are also easily copied with:

copy = old.slice(0);


You could do even better by keeping the state as a string; albeit with some modifications to the model. My only concern is the -1 since it's two characters. Using X, O, and - is a reasonable option, and it keeps the indices of the characters in the correct place.

"O-OXXX---" // a win for X


You'll also have some trouble with the high order functions since strings don't have them. Speaking of which...

High order functions come with a cost

While forEach, map, and some are awesome functions (and one of my favorite parts of JavaScript), they come with quite a bit of overhead compared to their for loop equivalents. The issue comes with the need to execute a callback function over and over as opposed to just running inline code.

Since your program is computation heavy,  you probably want speed over elegance. Converting all the high order functions to for loops should help considerably.

Certain states are duplicates of others

You could use a JavaScript object to keep track of the past states, so you don't have to build redundant tree branches.

Something like:

stateMap = {};
// ...
state = makeMove(possibleMove);

if (stateMap[state] !== undefined) {
  // check state ...
  stateMap[state] = node;
  // recurse next possible moves ...
}
else {
  node.child = stateMap[state];
}


This way if a state ever comes up again, it will be defined in stateMap, and you can reuse the node. However, the parent pointers may become a bit muddled, so you might want to keep a list of parent nodes, or preform a deep copy on the child's branch.

Other optimization ideas


Don't check every way to win each time. Each move only involves a subset of the possible ways.
Certain states are merely rotations of others, but that might be hard to utilize.




Review

Modularize

Your code is global and scattered. You could store it in a function to make it more portable and scalable:

var ticTacToeTree = (function () {
    function Node(state, toPlay) {
        this.toPlay = toPlay;
        this.bestValue = null;
        this.state = state;
        this.parents = [];
        this.children = [];
    };

    var head = new Node("---------", 'X');

    // The rest of your code

    return {
        head: head
    };
})();


Reusable code

checkIfWon could be used to check both players:

function checkWinner(state) {
  for (var i = 0; i &lt; winStates.length; i++) {
    if ("-" !==
         state[winStates[i][0]] ===
         state[winStates[i][1]] ===
         state[winStates[i][2]]) {
      return state[winStates[i][[0]];
    }
  }
  return "-"; // no one has won
}


Which prevents redundant calls:

function populateTree(currentNode, toPlay) {
  var winner = checkWinner(currentNode.state);

  if (winner === "-" &amp;&amp; checkDraw(currentNode.state)) {
    return currentNode.bestValue = 0;
  }
  else if(winner === "X") {
    return currentNode.bestValue = 1;
  }
  else if(winner === "O") {
    return currentNode.bestValue = 1;
  }

  // ...
}


Don't worry about getting a random move; you end up computing them all anyways:

for (var i = 0; i &lt; moves.length; i++) {
  move = moves[i];

  nextState = state.slice(0, move).concat(state.slice(move));

  if (stateMap[nextState] !== undefined) {
    var node = new Node(state, nextTurn(toPlay);
    node.parrents.push(currentNode);
    currentNode.children.push(node);
    populateTree(node, node.toPlay);
  }
  else {
    currentNode.children.push(stateMap[nextState]);
  }
}