Object.keys(object) возвращает массив строк, alert(array) приводит массив к строке, непримитивы приводятся к строке методом .toString(), array.toString() возвращает конкатенацию элементов через запятую. Поэтому кавычек, как идентификатора строки, вы не видите.
var array = ['x', '21', 21, 22]; // конкатенация: 'x' + ',' + '21' + ',' + 21 + ',' + 22
alert(array);
Все имена свойств структуры Object приводятся к строке, поэтому 21 становится '21' и перезаписывает предыдущий '21', доподлинно установить тип можно через typeof. Если всё же нужно сохранить тип имени, тогда следует использовать структуру Map, это одно из основных ее отличий.
var text = '';
var obj = { '21': 1, 21: 2, 22: 3 };
text += 'Object\n';
for (var key in obj) {
text += 'key: ' + key + ', type: ' + typeof key + ', value: ' + obj[key] + '\n';
}
var map = new Map([['21', 1], [21, 2], [22, 3]]);
text += 'Map\n';
for (var [key, value] of map) {
text += 'key: ' + key + ', type: ' + typeof key + ', value: ' + value + '\n';
}
alert(text);
Можно даже переписать .toString() как угодно.
Array.prototype.toString = function() {
var temp = [], i, v;
for (i = 0; i < this.length; i++) {
v = this[i];
if (typeof v == 'string') v = '"' + v + '"';
temp.push(i + ': ' + v);
}
return '[ ' + temp.join(', ') + ' ]';
};
var array = ['x', '21', 21, 22];
alert(array); // [ 0: "x", 1: "21", 2: 21, 3: 22 ]