getify / You-Dont-Know-JS

A book series on JavaScript. @YDKJS on twitter.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Scope and Closures - Ch.4 - Why Global Scope - `null` is not a global built-in

witemple-msft opened this issue · comments

(https://github.com/getify/You-Dont-Know-JS/blob/2nd-ed/scope-closures/ch4.md#why-global-scope)

Please type "I already searched for this issue":
I already searched for this issue.

Edition: (1st or 2nd)
2nd

Book Title:
Scope and Closures

Chapter:
4

Section Title:
"Why Global Scope"

Problem:

The section states:

image

null shouldn't be listed with the rest of these, as it's not a global variable like undefined. It's a keyword and behaves differently, can't be shadowed in the way undefined can be, etc.

Object.getOwnPropertyDescriptor(globalThis, "undefined");
// {
//   value: undefined,
//   writable: false,
//   enumerable: false,
//   configurable: false
// }
Object.getOwnPropertyDescriptor(globalThis, "null");
// undefined

null is its own token in the JavaScript grammar.

> const null = "foo";
const null = "foo";
      ^^^^

Uncaught SyntaxError: Unexpected token 'null'

I don't think this detail matters to the typical reader of this book. If you're using strict mode (which all JS devs should), you're not going to be trying to shadow/override any of these, so the fact that undefined could be but null couldn't, is so rarely encountered as to practically not matter. This section is telling my readers these are built-in and as such, actions like shadowing/overriding should always be avoided.

I don't understand what strict mode has to do with it.

Sure, it almost "practically [does] not matter," as the only difference is a very minor one. However, it's a minor difference in the exact sense that the chapter and book exhaustively (and otherwise, masterfully) detail.

I just found it strange that the section lists twenty-two specific items, all of which are exactly the same kind of thing except for null, which is uniquely and specifically different. If the goal is to tell readers that "the values are built-in" and "shadowing/overriding should always be avoided", why not also include true and false as well? They're keyword expressions just like null, and neither can they be shadowed (just as null cannot be shadowed, no matter how deviously one may scheme).

Do you really feel that this difference is so obscure that it makes more sense to include one item in a bullet point that forms an incorrect idea rather than omit null and let the other twenty-one examples simply be correct?

I don't understand what strict mode has to do with it.

Strict mode changes whether a developer sees thrown exception when trying to override/shadow the global undefined value (aka, property of the globalThis).

function foo() {
    undefined = 2;
}

function bar() {
    "use strict";
    undefined = 3;
}

foo();  // no problem
bar();  // TypeError exception thrown

So what I meant was, since most everyone either already is writing code in strict-mode, or at least their code is being transpiled to strict mode (or at the very least, they really should be being encouraged to use only strict-mode), they're not likely in the scenario where they're accidentally able to re-assign undefined (with silent failure) whereas failed assignment to null is noisy. In both cases, the failure is likely noisy for them.

IOW, in strict-mode, the distinction between null and undefined is even less than it is in non-strict-mode. That's what I meant in bringing up the topic of strict-mode.

Do you really feel that this difference is so obscure that it makes more sense to include one item...

I don't think most JS developers will ever think differently in their minds about null vs undefined (or true, for that matter) with respect to a question like "where they come from", which is overall the point of the book: explain where (what "scope") things come from, and all the rules that make that happen.

From the perspective of most non-specification-aware JS developers, the mental model they have is that these are each just special "values" that somehow happen to exist "globally" without needing to be referenced as properties of some object. The means by which undefined gets there is different than the means by which null gets there. But I don't think that distinction will really ever matter to a typical JS developer. In other words, for my readers, I think it's good enough to think of both of them as "globals".

The list does not include, nor does it pretend to, every single automatic "global" that exists in the JS environment. And no it doesn't include other things that similarly seem like global identifiers/values (true, false, etc)... but I put "etc" on most of the bullet points to indicate that it's an illustrative examples list rather than an exhaustive encyclopedic inventory. I don't know why I didn't include "etc" on the first bullet point, but as far as I can recall, such was my intention.


In retrospect, I perhaps might not have included null on the same bullet point or list as undefined, because I agree they are different -- had an issue such as this been brought up during writing/revision. Though, had I ended up omitting null from that list, I think I would have needed another list of values like null and true and such, and I would have needed to explain how the lists are different. My guess is, that might have distracted readers.

But leaving null off completely might have caused a different kind of distraction, in that a particular detail-oriented reader may have been left to wonder why I mentioned undefined but didn't mention null. So perhaps distraction/confusion was unavoidable.

Anyway, by combining null and undefined into the same bullet point, I avoided that confusion/distraction, at the extremely small risk (in my estimation) of someone either accidentally getting bitten in their own code by null not being a global property (pretty unlikely I think), or a reader (such as yourself) who's very spec-aware coming along and noticing the inaccuracy, and being bothered enough by it to raise an issue here.

Books are not replacements (fidelity wise, or utility wise) for the specification, nor are they intended to be. There's always artistic license and pedagogy and tone and style that get involved when you write prose about a technical thing. I made a choice here that bothers you, and that's OK. But that's what I mean when I say that although the bullet point is not entirely accurate, I think it's close enough that I am not concerned that the book has an important defect that should be remedied.

To keep things in context, we're having this discussion now, 2+ years after the book was published, and it's been printed and sold many thousands of times and read many thousands of times more. This is the first time the issue has been raised in all that time.

When I remarked that I didn't think such a detail mattered much to my readers, what I meant is, I don't think there's many (or any) readers who would care enough that they would expect me to issue a correction to their book.

As a side note, since this repository is intended as a reflection of (in free-to-read form) the text in the published and printed books, I don't hardly ever post a correction to the repo unless I am also willing to push that change into the publishing pipeline so that both the ebooks and printed books reflect the change.

The longer the books have been published, the higher that bar is. If I find a problem 2 days after publishing, I correct it. But if an issue is raised 2 years after publishing, I have to weigh whether it's serious enough or not to warrant divergence between the repo people read in the future and the tens of thousands of digital and physical copies of the book that already exist and will never get updated.

Closing for now. Feel free to add further discussion if you see fit.