WHY
The principle of least privilege is the idea that any user, program, or process should have only the bare minimum privileges necessary to perform its function.
Consider you've written code like the below at some point. We've declared a var and hope that it still has the same value. Well, right now it looks good.
var ninja = 'Naruto';
// ...
console.log(ninja); // Naruto
But say after a few months a jr. dev comes along and unknowing try to make a change like this.
var ninja = 'Naruto';
// ...
var ninja = 'Sasuke';
console.log(ninja); // Sasuke
console.log(ninja); // Sasuke -- oops!
So, you can easily see the issue here.
We have a naming collision problem.
You may think, we should just use const there. But the problem is not if the variable can be reassigned (because the developer if not aware could just modify your const to var anyways) but we have a naming collision problem.
So, the problem is: We have a problem where 2 different people wanna use the same semantic name for their purposes.
PSEUDO FIX
Since the problem could be thought of as mainly arising due to the declaration of the variable in the same scope. So, the natural fix coming to mind would be, to make use of different scopes and one simple way to do so could be by wrapping a function around it.
var ninja = 'Naruto';
function anotherNinja() {
var ninja = 'Sasuke';
console.log(ninja); // Sasuke
}
anotherNinja();
console.log(ninja); // Naruto
So, now those vars don't seem to collide anymore and the code seems to work well. But now the problem is, we have a named function in the same scope.
So it seems, we didn't solve the name collision problem, we just shifted it to a different variable name.
REAL FIX - IIFE
var ninja = 'Naruto';
(function anotherNinja() {
var ninja = 'Sasuke';
console.log(ninja); // Sasuke
})();
console.log(ninja); // Naruto
So, this code pattern you see is called an IIFE pattern i.e. Immediately Invoking Function Expression, which does exactly what it sounds like.
Using IIFE, we're creating a new scope and immediately invoking it.
Another use case: when you want to turn statements into expressions
Consider below example:
var ninja;
try {
ninja = fetchNinja();
}
catch (err) {
console.log(err);
}
If you wanna do something like this, since try-catch
is a statement it doesn't work in an expression position.
You can do something like this:
var ninja = (try {
ninja = fetchNinja();
}
catch (err) {
console.log(err);
})();
Summary
Try to follow "The principle of least privilege" whenever possible. Leverage the power of function scopes and IIFE patterns to enjoy the benefits of the principle like
Avoid naming collisions
Restrict code access
Ability to freely refactor code