Reading: You Don't Know JS Yet 2 (Scope & Closures) - Quick notes (from Chapter 6)

Anh-Thi Dinh
draft
⚠️
This is a quick & dirty draft, for me only!
⚠️
This note serves as a reminder of the book's content, including additional research on the mentioned topics. It is not a substitute for the book. Most images are sourced from the book or referenced.

All notes in this series

Infor & Preface

Chap 6 — Limiting Scope Exposure

Attention: decisions and patterns we apply across the whole program.

Least Exposure

  • How and why we use different levels of scopes (functions and blocks)? ← functions create their own scope, it’s normal but why we need blocks?
  • In Software Engineering, we have The Principle of Least Privilege (POLP - a concept in computer security that limits users' access rights to only what is strictly required to do their jobs) → its variation in this section is “Least Exposure” (POLE).
  • Following POLE, we want to minimize the exposure of variables in each scope.
  • [Bad idea] Placing all variables in the global scope, why?
      1. Naming Collisions: Identical names for variables or functions can lead to collisions, resulting in bugs.
      1. Unexpected Behavior: If access is granted to parts that are supposed to be private, other individuals may perform actions you did not intend.
      1. Unintended Dependency: If developers outside of your program create a dependency on some "supposed to be private" parts of your program, future changes to these parts could unexpectedly affect these external dependencies.
→ Exposing min necessary, keeping everying else as private as possible.
  • In order to block the variable to the block scope, use let or const, don’t use var!
    • 1function diff(x, y) {
      2  console.log(tmp); // ReferenceError with "const" and "let", undefined with "var"
      3  if (x > y) {
      4    const tmp = x; // or let or var
      5    x = y;
      6    y = tmp;
      7  }
      8  return y - x;
      9}

Hiding in Plain (Function) Scope

  • Use let or const to block the scope to lowest level but how to hide var or function too?
  • Hide var by wrapping it by a function.
    • 1var cache = {} // will be in the global scope
      2function factorial(x) {
      3	if (x < 2) return 1; if (!(x in cache)) {
      4		cache[x] = x * factorial(x - 1);
      5	}
      6	return cache[x];
      7}
      8factorial(6); // 720
      1// outer scope
      2function hideTheCache() {
      3	// middle scope
      4	var cache = {}
      5	function factorial(x) {
      6		if (x < 2) return 1; if (!(x in cache)) {
      7			cache[x] = x * factorial(x - 1);
      8		}
      9		return cache[x];
      10	}
      11}
      12var factorial = hideTheCache();
      13factorial(6); // 720
      Hide cache. ← Weakness: different hideTheCache for different variables like cache → collisions!
      1var factorial = (function hideTheCache() {
      2	var cache = {}
      3	function factorial(x) {
      4		if (x < 2) return 1; if (!(x in cache)) {
      5			cache[x] = x * factorial(x - 1);
      6		}
      7		return cache[x];
      8	}
      9})() // () means "immediate invoke the function"
      Don’t affraid of the collisions. We can use again hideTheCache in other places because it isn’t in the outer scope. Read again section “Function Name Scope”.
❇️ Invoking Function Expressions Immediately
The last () in the previous code is call Immediately Invoked Function Expression (IIFE). It’s useful to create a scropt to hide var/func.
1// standalone IIFE -> "()" surround function is required
2(function(){ .. })();
3
4// with a name -> "()" surround function isn't required
5(function namedIIFE(){ .. })();
6function nameIIFE(){...}()
IIFE.