re-ordering a JavaScript object's keys alphabetically
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 30 Oct 2017 | |
// re-ordering an object's keys alphabetically with sortKeysFor(anObject) | |
/* | |
Earlier this year a colleague was tasked with modifying an application that defined | |
a very large object (i.e., containing 20+ properties). The troubling part was that | |
the object was defined twice, first in an if-block, then in an else-block. That made | |
the differences between the definitions difficult to detect just by scanning. | |
The first part of the solution was to collapse two if-else statements into a single | |
default definition, then when some other condition were true, to modify or add | |
properties as needed. | |
The second part involved refactoring the base object so that the properties were | |
defined in alphabetical order, top to bottom, for easier scanning by the human eye. | |
"Is there some fast way to do that," said our colleague, obviously dreading the | |
copy-paste-modify exercise. | |
This was in an ES5 code base, so first up is an ES5 function that re-writes an | |
object in this way. Further down (way down), shows a more direct approach if | |
you're working on an ES6 object with short-cut notation... | |
*/ | |
// Our test object will contain "reduplicate" keys pointing to same-name functions. | |
// Create those functions first... | |
var z = function(){}, | |
y = function(){}, | |
a = function(){}, | |
b = function(){}, | |
w = function(){}, | |
h = function(){}, | |
t = function(){}, | |
m = function(){}; | |
// ES5 - the long way | |
// Map obj.z to z, etc. | |
var obj = { | |
z: z, | |
y: y, | |
a: a, | |
b: b, | |
w: w, | |
h: h, | |
t: t, | |
m: m | |
} | |
// re-map the object with sorted keys | |
var sortKeysFor = function(obj) { | |
return Object.keys(obj).sort().reduce(function(map, key) { | |
map[key] = key // <= here we just use the key, we're interested in the output, not the literal object. | |
return map | |
}, {}) | |
} | |
// print object | |
console.log(sortKeysFor(obj)) | |
// => Object { a: "a", b: "b", h: "h", m: "m", t: "t", w: "w", y: "y", z: "z" } | |
// stringify object | |
console.log(JSON.stringify(sortKeysFor(obj))) | |
// => {"a":"a","b":"b","h":"h","m":"m","t":"t","w":"w","y":"y","z":"z"} | |
var string = JSON.stringify(sortKeysFor(obj)).replace(/\"|\'/g, '').split(',').join(',\n ') | |
console.log(string) | |
/* and finally, the output "source" can be copied: | |
{a:a, | |
b:b, | |
h:h, | |
m:m, | |
t:t, | |
w:w, | |
y:y, | |
z:z} | |
*/ | |
/* Now for the ES6 approach - a much shorter solution. */ | |
// Use destructuring notation to shorten the object property entries as | |
var struct = { z, y, a, b, w, h, t, m } | |
// JSON.stringify won't work on that | |
console.log( | |
JSON.stringify(struct) | |
) | |
// literally => {} | |
// Instead, use `join` directly to concatenate keys in sorted order. | |
console.log( | |
'{ ' + Object.keys(struct).sort().join(', ') + ' }' | |
) | |
// => { a, b, h, m, t, w, y, z } | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment