Does anyone know the reasoning behind the change from throwing an error when passing a primitive to Object.keys
to silently coercing the primitive to an object and returning the result?
I'm not sure that anyone would expect Object.keys('abc')
to return [0, 1, 2]
, and it seems to violate the prime directive of "don't break the web". What if some website has code wrapping a call to Object.keys
in a try/catch to handle callers mistakenly passing a primitive?
This is why I feel there must be a strong rationale behind the change. I would be very interested if anyone out there has some information about this.
I couldn't find any mention of this decision on esdiscuss, so I can only offer my own perspective.
As a commentor points out, this is part of larger trend in ES 2015 to allow non-object inputs more broadly. In the ES 2015 spec, the phrase, "In the previous edition, a non-object argument always causes a TypeError
to be thrown," appears in reference to 10 different methods on Object
.
For one, this change brings the behavior of Object.keys
into congruity with the behavior of for-in
loops, which have always been able to operate on primitives. Considering that the specification already required order to match between Object.keys
and for-in
, requiring the same set of valid operands seems unsurprising.
This change seems nearly as harmless as can be to existing code while greatly reducing the brittleness of Object.keys
. Even in your case of a try-catch, it's difficult to imagine a case where successful Object.keys
execution causes an actual problem. I can easily imagine code like this:
try {
var keys = Object.keys(input);
} catch {
// oops, input was a primitive; call `new [Constructor]` to wrap it
var keys = Object.keys(
new input.constructor(input)
);
}
But this doesn't break when Object.keys
doesn't error out; a successful Object.keys
call makes the catch
code obsolete.
Of course there might exist, somewhere, code like this:
try {
var keys = Object.keys(input);
} catch {
// oops, input was a primitive; that unlocks the secret prize
giveUserAFreePuppy();
}
Basically, what I'm trying to say, through a very silly example, is that the cases where skipping a catch
block would be truly problematic for the operation of some code seem so far-fetched that breaking such code seems a small price to pay to get a less brittle Object.keys
function.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With