Jump to ratings and reviews
Rate this book

You Don't Know JS Yet: Scope & Closures

Rate this book
Scope & Closures, the second book in the new edition series, dives deep into how and why to organize variables into different buckets of scope, limiting scope over-exposure and improving code maintainability. On top of lexical scope, closure empowers functions with memory, preserving variables across calls. Modules leverage scope and closures to encapsulate data and behavior.

270 pages, ebook

62 people are currently reading
172 people want to read

About the author

Kyle Simpson

37 books360 followers
Kyle Simpson is an Open Web Evangelist from Austin, TX, who's passionate about all things JavaScript. He's an author, workshop trainer, tech speaker, and OSS contributor/leader.

Ratings & Reviews

What do you think?
Rate this book

Friends & Following

Create a free account to discover what your friends think of this book!

Community Reviews

5 stars
41 (45%)
4 stars
39 (42%)
3 stars
10 (10%)
2 stars
1 (1%)
1 star
0 (0%)
Displaying 1 - 7 of 7 reviews
Profile Image for Iain Davis.
14 reviews1 follower
March 15, 2025
TL;DR
I found in this book some clarifications of concepts that were useful to me. I also found it to be overly verbose, a bit pedantic, too opinionated and prescriptive, and just too long. I might recommend it as a resource for a young JavaScript developer, but I would expect anyone with a few years under their belt to have already learned or intuited much of this, and many of the portions they would not have intuited, I question the value of learning as a sort of prophylactic against encountering a confusing situation in the future. I would recommend in place of this book "Eloquent JavaScript", which I have not read in years, but found to be a better read and more useful in the topics it chooses to cover. I will be re-reading Eloquent JavaScript and writing a review here at some future date (in reality, I'll be reading the new 4th edition for the first time). I will also continue reading the You Don't Know JS series (in it's first edition) and reviewing those books as well.

Background
I've been aware of this series of books for a while, and intended to read them at some point, but never actually got around to it until recently. I landed and interview with a tech company I was excited to work for, and reading these books was part of their recommended prep material. I didn't get the job, but I did decide that maybe it was time I waded into "You Don't Know JS".

I typically like to review a book shortly after I read it, but between job hunt and personal projects, I've been a bit lax on that front. This will therefore serve as a review of the first two books in this series together, both of which I have read recently.


• You Don't Know JS Yet: Get Started
• You Don't Know JS Yet: Scope & Closures


I have read these books in their second edition. The remaining books in the series have not had the second editions completed yet and so I will be reviewing the first editions of those (titled "You Don't Know JS" rather than the somewhat softened "You Don't Know JS Yet" of the second editions), when I get around to them.

The Books
First, a bit of a disclaimer. I am going to be critical of these books. I find a fair bit about the books could be better, and I disagree with the author about a fair few of his positions. That should not detract, though, from the fact that I did find value in these books.

The author is at some pains to prepare the user for a challenging read, suggesting repeatedly that you should take each section in isolation, and then give it time to percolate in your mind and practice the concepts within before moving on to the next section, even for experienced JavaScript developers. I'm not sure this is necessary. Most of what is in these books is going to seem pretty intuitive to any JavaScript developer who's been working for a little while and paying attention. For those things that don't seem intuitive, I think most developers will have adopted conventions to workaround or avoid those situations. The admonition that these concepts are simultaneously fundamentally difficult and necessary to grasp seems to me a justification for the length of the series (six books!) when most of what I found illuminating and valuable about it could have been expressed in a few relatively short blog posts.

Getting Started
The first book serves as a general high-level survey of the concepts that will then be developed more fully in subsequent books. It does give a few clarifications I found to be useful:

• the actual differences between equality operators
• when type coercion is allowed and when it is explicitly disallowed
• the behavior of the `this` keyword in various situations


The author has some very strong opinions that seem unjustified, at least in their vigor, if not in principle. As an example, he makes clear over and over his distaste for arrow functions. He makes some strong arguments about anonymous functions that I am judiciously taking to heart, but his distaste for the arrow function format seems mostly to be that there are so many ways to express them. Which seems a weird thing to get hung up on to me. And also out of step with the reasoning behind other arguments he makes, when he explicitly advocates for retaining syntax that doesn't actually seem to add much value. It has a bit of the flavor of that Grandpa Simpson meme "Old Man Yells At Cloud". I'll talk more about arrow functions when I get to the next book.

A lot of this book is dedicated to explaining things you probably don't need explained if you already write JavaScript. How to write classes. How iterators work. Spread and rest operators and destructuring. Prototypes. If my experience with Scope & Closures is indicative, then I expect each of these topics to be dealt with in greater detail in a subsequent book, so I'm not sure that I necessarily needed a book that essentially serves as a 100-page introductory chapter.

Scope & Closures
This book deals with scope and its consequences. That discussion takes into some semi-peripheral topics as well, such as self-executing functions, interactions between the compiler and the runtime environment and how that produces the observable behavior of scopes, and some of the history leading to `var` `let` and `const`

Again, my biggest criticism of this book is that a great many developers can take a great deal of this content as read. I understand how function scope works, and how closures work. The last two chapters of the book are committed to modules and closures, which are probably the greatest value in the book to the greatest number of developers. A great deal of the rest is the author's (in my opinion often unjustified) opinions, basics that you likely don't need, and edge cases that may be interesting, but are unlikely to ever come up in your career, especially if you follow some fairly common conventions (like not shadowing parameter names in your function definitions).

The author argues that this knowledge is inherently valuable. I'm not sure I agree. I'm a big believer in knowing your tools. But I also feel like you can spend way too much time crawling down rabbit holes in the hope that some day you might need whatever knowledge that particular rabbit is hoarding. I prefer to have enough knowledge to accomplish what I need to, and the curiosity and skill necessary to untangle whatever particular confusing ball of wax I encounter when I encounter it.

What value did I find? I appreciate having an improved understanding of the relationship between `var` and `let` and I suppose having a bit of the rationalizations behind those decisions is interesting too. I think a discussion of how to use closures and modules is valuable.

Where do I think the author goes wrong?

Opinions. So many opinions. Things are presented as "this is the right way" rather than "these are alternative approaches and I prefer this one". And his choices are often strange, at least in my eyes.

var, let, const

The author gives a pretty good explanation of `var` and `let`. But he strongly advocates for the continued of `var` for all function-scoped variables. It's emphasized enough that it almost seems defensive. For my part, I cannot find a convincing justification for this insistence. He says it's semantically clearer, and that `var` communicates that a variable belongs to the entire function, rather than to some internal block. This depends entirely on the arbitrary decision to treat the body of a function as conceptually different than any other fenced off block. And the only justification for that decision seems to be to provide a justification to keep `var` around. Alternatively, you can choose to treat the body of a function as equivalent to any other block of code that has a scope, and use `let` to convey that the variable belongs to the particular block it appears in, whether that block is a function or not. It seems like a lot of mental gymnastics to justify preserving an additional keyword to remember, increasing cognitive load, because I now have to treat these essentially equivalent concepts as if they are different.

The author also advocates the near-total avoidance of the `const` keyword, on the basis that it will confuse developers when they discover that an object or array stored in a const is still mutable... it's just the reference to the object that is protected from mutation, and not the content itself: reference immutable versus value immutability. First, I think this sort of thing can occasionally trip up inexperienced devs, but I also think they get over it pretty quickly. It's not that hard a concept to think of a `const` array as a box, and to know that I can change the contents of the box, but I can't replace the box itself with a different box. Secondly, explaining these kinds of implementation details and consequences is the entire purpose of this book. It's whole ethos is that implementation details of the language, and their consequences, are worth knowing, and you shouldn't discard them just because they come with some unintuitive wrinkles.

The one positive thing I did take away from this portion of the book is a potentially truly valuable use-case for `var`:

while (!end) {
/* do loop body stuff */
if (endReason) {
var end = true;
}
}


By using `var`, we move the `end` variable into the outer scope and hoist it to the top of that scope, saving us having to declare a variable outside the loop, only so that it will be accessible to the loop-continuation evaluation. This seems like a valid and useful case for `var`: it preserves the natural reading order. Having to jump from one line to another in the code to understanding what it is doing is unnecessary cognitive load, and this nicely deals with it. On the other hand, I wonder if this wouldn't be confusing for some devs... it relies on implicit behavior, which could amount to hiding details important to the understanding of what is actually happening here from a dev who doesn't implicitly understand what `var` is doing here. On the fence about this one. But I suspect I will probably use it because it reads more naturally than this:

let end = false;
while (!end) {
/* do loop body stuff */
if (endReason) {
end = true
}
}


using blocks to create scopes
The author advocates using synthetic blocks (i.e., open and closed curly braces: '{}') to limit the scope of variables that are not directly used in the return value of the function. The justification is to preserve the least-exposure and least-privilege, and even resorts to an argument that is semantically easier to understand.

Please, do not do this. If you ever submit a PR for my review, and it has code like this example from the book (comments stripped for brevity) in it:

if (somethingHappened) {
/* unnecessary block scope introduced solely to enforce least-exposure */
{
let msg = somethingHappened.msg();
notifyOthers(msg)
}
recoverFromSomething();
}

expect to be asked to change it. I do not want to have to go chasing down opening and closing braces within your function to determine which variables are in scope at which lines. I especially do not want to do this to any level of nested blocks. This is least-privilege taken to the point of dogma. You should apply the principle of least privilege when it serves a purpose. Here it only serves to introduce unnecessary complexity and cognitive load into a simple function. You are not at any kind of risk be exposing the `msg` variable to the wider function scope. This is particularly puzzling because the author makes essentially the same argument I'm making here in favor of avoiding the use of the `const` keyword -- to paraphrase: it might be more secure but there are much, much bigger and more immediate concerns to give your attention to.

I would argue that, if your function is complex enough to need decomposition, then any part of your function which is self-contained enough to be extractable from the function then deserves to be its own function and have a name that describes what it does. Mr. Simpson clearly knows more about JavaScript internals than I do, and maybe he knows a reason related to performance or compiler behavior why you shouldn't extract such blocks into functions, but if he does, his book failed to communicate it to me.

anonymous and arrow functions
The author hates arrow functions. Really hates them. And he thinks every function always should be explicitly named, as in this form:

function myFunc() {
/* function body */
}


or this:

//
invocationOfAFunctionConsumingFunction(function myConsumedFunction() {
/* my consumed function body */
});


any kind of implicit naming of a function, like this, is not adequate:

const myFuncVar = function() {

}


This is one point where the author and I mostly agree, and I have changed my habits to include more use of the `function` keyword in place of arrow funcs. It helps a little with debugging. But for my taste, he's again much too dogmatic about it. He asserts that absolutely every function must be named and arrow functions should never be used.

Let me share an example.

The author asserts that this:


[ 1, 2, 3, 4, 5].filter(function(v){ return v % 2 == 1;})


is less readable than this, owing to the named function:

[ 1, 2, 3, 4, 5].filter(function keepOnlyOdds(v){
return v % 2 == 1;
})


And he's right! It is! But do you notice anything else about this code? It doesn't do anything! Both of these values are expressions, but they are expressions without effect. If you found this in the middle of a series of instructions, it would be the equivalent of finding the words "57 Chevrolet Bel Air" appropos of nothing in the middle of a recipe for chocolate cake. It connects to nothing before or after it. You could append a `forEach` or some similar consumer to produce a side-effect from these values, and then you might make this argument a little stronger, but it seems to me that the mostly likely thing to do with the presented operation is to assign it to a variable and that the author had to explicitly omit this step to make the case he's trying to make. I would argue that this:

const oddNumbers = [1, 2, 3, 4, 5].filter(function(v){ return v % 2 == 1;})

is more readable than either of the given examples. It's more readable than the first example because it assigns a name to the output which gives semantic context for the calculation, and it's more readable than the second example by simply including less boilerplate.

I would argue that this is more readable still:

const oddNumbers = [1, 2, 3, 4, 5].filter((n) => n % 1 === 1)

There are very few elements in that expression that do not convey some functional intent, and I do not believe I would struggle to identify the source of an error that occurred within the arrow function. Brevity has value.

Conclusion
I found a little value, and a lot to disagree with in these books. For my money, if you're looking for a valuable exploration of the JavaScript language, I would recommend instead "Eloquent JavaScript". To be fair, I haven't read it recently, but I did find it very illuminating when I did read it (and I will re-read and review it sometime in the future). I found this book to be a bit pendantic, overly opinionated, and inconsistent in it's justifications for many of its opinions.
Profile Image for Lucy  Batson.
468 reviews9 followers
February 12, 2021
I'm not a fan of Kyle Simpson's writing style, I think he understands JavaScript really well and is incapable of going off on tangents that make what he's talking about harder to parse rather than easier. That aside, this is a decent overview of how scope and closures work in JS, with a LOT of detail on corner-cases and examination of the problem from every conceivable angle.
Profile Image for Vibhor Rawal.
55 reviews7 followers
October 13, 2021
3.5 stars

This book is actually less "you should totally read my writing as sacred text" (first one was kinda) and more "here also this, you can read about that also". So I find it better than first book, but it did not feel in-depth (part of lore is the expectations are also set high, that we'll go in depth)

A decent read nonetheless.
2 reviews
March 21, 2022
Loads of useful info for JS devs (from novice to expert) but some of the techniques seem to be dated. Recent code usually won't make use of other module systems than ESM for instance.
Profile Image for Carlos.
11 reviews1 follower
September 13, 2022
If you want to deep dive into JavaScript scopes and closures, read this book.
Displaying 1 - 7 of 7 reviews

Can't find what you're looking for?

Get help and learn more about the design.