DEV Community

loading...

JavaScript and the object keys automatic deduplication

Felippe Regazio
web developer - js, [s]css, node, php, python - intp, lifelong learner, father, skateboarder. a strange carbon-based lifeform.
・3 min read

Imagine that you have a hard coded JS config file somewhere on your project (or any kind of object). Something like that:

const whatever = {
  base: 'anything',
  port: 123456,
  secret: 'just-to-illustrate-asdjf23u',
  port: 123568,
};
Enter fullscreen mode Exit fullscreen mode

Probably you saw the error. The "port" key is duplicated. This is a very specific situation, when a key is duplicated at declaration level. Although it is very rare to pass to the production because will probably be spotted on lint, code review or test phase, i would like to talk about it a little bit.

JavaScript will silently normalize this object with no error or warning. This is understandable: if the object was created with a duplicated keys it would be an invalid object by definition. So there were 2 choices:

  1. Deduplicate keys before create the object
  2. Raise an error

JS will deduplicate the object keys (remove duplicated keys) for you at runtime, resulting in:

{
  base: 'anything',
  secret: 'just-to-illustrate-asdjf23u',
  port: 123568,
}
Enter fullscreen mode Exit fullscreen mode

Buuut, the object is still misspelled. Of course, as already said and for the sake of your project, you are probably using a linter, a superset like TS and have a good code review and test process and this error wont pass. This also reinforce the good practices and automation tools on your code.

Even if you are in 'use strict', no error, no warning, no information will be thrown. Try to execute the following code:

'use strict'

const test = {
  fizz: 'fizz',
  fizz: 'buzz'
};

console.log(test); // { fizz: 'buzz' }
Enter fullscreen mode Exit fullscreen mode

This is acceptable when you think that an object with duplicated keys would be an structure violation, so the object is normalized even in "strict mode" as a design decision, i guess. Again no error is thrown. Here is what the RFC says about it:

Each own property of an object must each have a key value that is distinct from the key values of the other own properties of that object - https://262.ecma-international.org/11.0/#sec-object-type

As you saw, there is nothing about how this kind of violation must be treated (or i didnt found it till now). This is also a kind of thing you cant validate at runtime. You can think in stringify and validate, check the structure on a for loop, but everything will fail because the object is normalized before anything. Do the test:

const test = Object.freeze({
  fizz: 'fizz',
  fizz: 'buzz'
});

console.log(test); // { fizz: 'buzz' }
Enter fullscreen mode Exit fullscreen mode

As you can see, the object was normalized and then freezed. Anything you run against the object will run on a ready-normalized object. But as said, the "typo" on the object declaration remains there.

This is of course a very very specific discussion, but shows us the importance of process and tools not only at runtime, but also at lexical level, since some errors are very tricky and tiny and can be spotted only that way.

Some people argue that this behavior is due to features like spread operator. As I have no evidence of yes or no, I would prefer to hear the comments.

Anyway, a duplicated key on a config object can be confusing and lead to misinformation. You read a value but the server is running against another because you didn't notice the same duplicated key/value below, or at best, its just an annoying lexical error. Its very easy to avoid, unlikely to happen,
but I thought it would be nice to talk about it.

Discussion (0)