First JavaScript game: Tic Tac Toe
Your code's pretty good actually. I don't see any of the typical beginner's syntactical pitfalls. Kudos! (Though I would prefer gameOver, given its name, to be false while the game's running).

Structurally, there are many ways to build it. I'd probably split things into objects or constructors (aka classes).

For instance, I'd make the board an object with its own methods for marking a square, checking for wins, resetting, etc.. Similarly, the players and the turn-taking could be modelled. It may be overkill for a simple Tic-Tac-Toe game, but the resulting code will be simpler to read (I think). It's basically the same strategy as creating views in MySQL to encapsulate complex/reusable queries.

For instance something like this (not a complete implementation)

// Constructor
function Board() {
  this.squares = new Array(9);
}

// Prototype functions (i.e. methods)
Board.prototype = {
  // get number of marked squares
  occupied: function () {
    var i, l, count = 0;
    for( i = 0, l = this.squares.length ; i &lt; l ; i++ ) {
      count += this.squares[i] ? 1 : 0;
    }
    return count;
  },

  // get a row
  row: function (index) {
    var i = index * 3;
    return this.squares.slice(i, 3);
  },

  // get a column
  column: function (index) {
    var i, l, column = [];
    for( i = index, l = this.squares.length ; i &lt; l ; i += 3 ) {
      column.push(this.squares[i]);
    }
    return column;
  },

  // get diagonal squares
  // index 0: from top-left
  // index 1: from top-right
  diagonal: function (index) {
    var step = index ? 2 : 4,
        squares = [];
    index = index ? 2 : 0;
    while( squares.length &lt; 3 ) {
      squares.push(this.squares[index]);
      index += step;
    }
    return squares;
  }
};


Edit: The above code has some issues. One was a straight-up typo on my part (fixed now). The other is a little more subtle: slice() will ignore undefined elements in an array. So (new Array(3)).slice(0) → [] instead of [undefined, undefined, undefined]. This could obviously cause trouble, as the array will be shorter than one might assume. So the array should either be seeded with values (zeros for instance), or the slice-call should be replaced with something similar to what column() is doing in the above: Looping and pushing values, even if they're undefined.

Then you can call new Board() to get a, well, a new board. That board, in turn, provides functions for determining the state of play. (Note that most of these functions can be simplified using array functions like forEach and win-conditions can be checked with reduce or a homemade array-sum function. However, that's an exercise for the reader).

With regard to visual output, you could start by simply "printing" to &lt;pre&gt; element on the page instead of the console. A minor step, yes, but just to get the hang of DOM manipulation/interaction. Actually, using your code, I've done that here. Of course, the real next step is using elements for each square, have them react to clicks, etc..

For that, you could consider simply letting the DOM itself handle the state. I.e. rather than a separate array of values, simply use the elements themselves and their attributes to determine if/how a square is marked.

For now, though, I'll stop here. See if you get something useful out of a more object oriented approach, before moving on the HTML GUI. The reason I'm suggesting this, is that the DOM is object oriented already, so getting the game logic on that footing will likely make creating the GUI easier/simpler. At least you're bound to learn something :)