Today I Learned - Rocky Kev

TIL refactoring object lookups to avoid looking at the prototype chain

POSTED ON:

TAGS:

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!

MDN - hasOwnProperty()


Related TILs

Tagged:

TIL not using try/catch block with promises for error catching

You shouldn't use a try/catch block inside the Promise Definition. Your promise is already doing that.

TIL using proxies for reactivity

A Proxy let you detect when someone gets, sets, or updates a property on an object, and run code when they do. But why? This usecase -- when you add/update the object, it also updates localStorage!

TIL the difference between partial application and currying

Partial application transforms a function into another function with smaller set of arguments. Currying creates nesting functions according to the number of the arguments of the function. Each function receives an argument.