The . is an operator. The 2 is a number. The x is (treated as) a property name.
A floating-point numeric constant must not have embedded spaces. Thus, 2 .x is an expression calling for the constant 2 to be promoted to a Number object, and then the property called "x" is examined. There isn't one, of course, so the value is undefined.
You can get the same effect a little more explicitly with
alert((2).x);
Note that
alert("Hello".x);
is somewhat similar: in that case, it's not a numeric constant, it's a string constant. It's less peculiar because there's no syntactic funny business involved, but otherwise the interpreter does similar things when evaluating. The string constant is first converted to a String object, and then the "x" property is fetched.
edit — to clarify a little, 2.x is an error because it's parsed as a numeric constant ("2.") followed by the identifier "x", and that's a syntax error; two values placed next to each other like that with no intervening operator do not form any sort of construct in the language.