TIL refactoring object lookups to avoid looking at the prototype chain
POSTED ON:
TAGS: advanced javascript refactor mdn
I'm a big fan of object lookups.
Let's start with the first issue:
function getPokemon(type) {
let pokemon;
switch (type) {
case 'Water':
pokemon = 'Squirtle';
break;
case 'Fire':
pokemon = 'Charmander';
break;
case 'Plant':
pokemon = 'Bulbasaur';
break;
case 'Electric':
pokemon = 'Pikachu';
break;
default:
pokemon = 'Mew';
}
return pokemon;
}
console.log(getPokemon('Fire')); // Result: Charmander
You can refactor it to look like this:
const pokemon = {
Water: 'Squirtle',
Fire: 'Charmander',
Plant: 'Bulbasaur',
Electric: 'Pikachu'
};
function getPokemon(type) {
return pokemon[type] || 'Mew';
}
console.log(getPokemon('Fire')); // Result: Charmander
// If the type isn't found in the pokemon object, the function will return the default value 'Mew'
Sweet right?
Cleaner execution, and easier to read.
But Daniel Worsnup pointed out a major issue.
In other words, you can access the prototype chain, which opens up some potential vulnerabilities or terrible side effects!
The solution would be to do this instead:
const pokemon = {
Water: 'Squirtle',
Fire: 'Charmander',
Plant: 'Bulbasaur',
Electric: 'Pikachu'
};
function getPokemon(type) {
return pokemon.hasOwnProperty(type) ? pokemon[type] : 'Mew';
}
console.log(getPokemon('Fire')); // Result: Charmander
We check with a hasOwnProperty()
.
The hasOwnProperty() method returns a boolean indicating whether the object has the specified property as its own property (as opposed to inheriting it).
In other words, it'll only look locally for properties, and does not navigate up the prototype chain!
Related TILs
Tagged: advanced