# You Don't Know JS Yet

## Metadata
- Author: [[Kyle Simpson, Simon St.Laurent, and Brian Holt]]
- Full Title: You Don't Know JS Yet
- Category: #books
## Highlights
- So alert(..) and console.log(..) are not defined by JS. But they look like JS. They are functions and object methods and they obey JS syntax rules. The behaviors behind them are controlled by the environment running the JS engine, but on the surface they definitely have to abide by JS to be able to play in the JS playground. ([Location 260](https://readwise.io/to_kindle?action=open&asin=B084BNMN7T&location=260))
- Tags: [[blue]]
- The developer console is not trying to pretend to be a JS compiler that handles your entered code exactly the same way the JS engine handles a .js file. It’s trying to make it easy for you to quickly enter a few lines of code and see the results immediately. These are entirely different use cases, and as such, it’s unreasonable to expect one tool to handle both equally. ([Location 283](https://readwise.io/to_kindle?action=open&asin=B084BNMN7T&location=283))
- Tags: [[blue]]
- Don’t trust what behavior you see in a developer console as representing exact to-the-letter JS semantics; for that, read the specification. Instead, think of the console as a “JS-friendly” environment. That’s useful in its own right. ([Location 286](https://readwise.io/to_kindle?action=open&asin=B084BNMN7T&location=286))
- JavaScript is most definitely a multi-paradigm language. You can write procedural, class-oriented, or FP-style code, and you can make those decisions on a line-by-line basis instead of being forced into an all-or-nothing choice. ([Location 300](https://readwise.io/to_kindle?action=open&asin=B084BNMN7T&location=300))
- The idea is that JS developers can write code with confidence that their code won’t stop working unpredictably because a browser update is released. This makes the decision to choose JS for a program a more wise and safe investment, for years into the future. ([Location 307](https://readwise.io/to_kindle?action=open&asin=B084BNMN7T&location=307))
- Tags: [[blue]]
- HTML and CSS, by contrast, are forwards-compatible but not backwards-compatible. ([Location 322](https://readwise.io/to_kindle?action=open&asin=B084BNMN7T&location=322))
- Tags: [[blue]]
- Transpilation and polyfilling are two highly effective techniques for addressing that gap between code that uses the latest stable features in the language and the old environments a site or application needs to still support. Since JS isn’t going to stop improving, the gap will never go away. Both techniques should be embraced as a standard part of every JS project’s production chain going forward. ([Location 415](https://readwise.io/to_kindle?action=open&asin=B084BNMN7T&location=415))
- Tags: [[blue]]
- So what do “parsed” languages have in common with “compiled” languages? First, all compiled languages are parsed. So a parsed language is quite a ways down the road toward being compiled already. In classic compilation theory, the last remaining step after parsing is code generation: producing an executable form. ([Location 440](https://readwise.io/to_kindle?action=open&asin=B084BNMN7T&location=440))
- Tags: [[blue]]
- JS source code is parsed before it is executed. The specification requires as much, because it calls for “early errors”—statically determined errors in code, such as a duplicate parameter name—to be reported before the code starts executing. Those errors cannot be recognized without the code having been parsed. ([Location 446](https://readwise.io/to_kindle?action=open&asin=B084BNMN7T&location=446))
- Tags: [[blue]]
- I think it’s clear that in spirit, if not in practice, JS is a compiled language. And again, the reason that matters is, since JS is compiled, we are informed of static errors (such as malformed syntax) before our code is executed. That is a substantively different interaction model than we get with traditional “scripting” programs, and arguably more helpful! ([Location 467](https://readwise.io/to_kindle?action=open&asin=B084BNMN7T&location=467))
- Tags: [[blue]]
- In 2013, engineers from Mozilla Firefox demonstrated a port of the Unreal 3 game engine from C to JS. The ability for this code to run in a browser JS engine at full 60fps performance was predicated on a set of optimizations that the JS engine could perform specifically because the JS version of the Unreal engine’s code used a style of code that favored a subset of the JS language, named “ASM.js”. This subset is valid JS written in ways that are somewhat uncommon in normal coding, but which signal certain important typing information to the engine that allow it to make key optimizations. ASM.js was introduced as one way of addressing the pressures on the runtime performance of JS. ([Location 472](https://readwise.io/to_kindle?action=open&asin=B084BNMN7T&location=472))
- Tags: [[blue]]
- WASM is a representation format more akin to Assembly (hence, its name) that can be processed by a JS engine by skipping the parsing/compilation that the JS engine normally does. The parsing/compilation of a WASM-targeted program happen ahead of time (AOT); what’s distributed is a binary-packed program ready for the JS engine to execute with very minimal processing. ([Location 483](https://readwise.io/to_kindle?action=open&asin=B084BNMN7T&location=483))
- Tags: [[blue]]
- WASM is additionally motivated by the desire to bring more parity for non-JS languages to the web platform. For example, if a language like Go supports threaded programming, but JS (the language) does not, WASM offers the potential for such a Go program to be converted to a form the JS engine can understand, without needing a threads feature in the JS language itself. ([Location 487](https://readwise.io/to_kindle?action=open&asin=B084BNMN7T&location=487))
- Tags: [[blue]]
- Why strict mode? Strict mode shouldn’t be thought of as a restriction on what you can’t do, but rather as a guide to the best way to do things so that the JS engine has the best chance of optimizing and efficiently running the code. Most JS code is worked on by teams of developers, so the strict-ness of strict mode (along with tooling like linters!) often helps collaboration on code by avoiding some of the more problematic mistakes that slip by in non-strict mode. ([Location 506](https://readwise.io/to_kindle?action=open&asin=B084BNMN7T&location=506))
- Tags: [[blue]]
- Most strict mode controls are in the form of early errors, meaning errors that aren’t strictly syntax errors but are still thrown at compile time (before the code is run). For example, strict mode disallows naming two function parameters the same, and results in an early error. Some other strict mode controls are only observable at runtime, such as how this defaults to undefined instead of the global object. ([Location 510](https://readwise.io/to_kindle?action=open&asin=B084BNMN7T&location=510))
- If you find yourself feeling handcuffed, trying to work around strict mode, that should be a blaring red warning flag that you need to back up and rethink the whole approach. ([Location 515](https://readwise.io/to_kindle?action=open&asin=B084BNMN7T&location=515))
- Tags: [[blue]]
- The only valid reason to use a per-function approach to strict mode is when you are converting an existing non-strict mode program file and need to make the changes little by little over time. Otherwise, it’s vastly better to simply turn strict mode on for the entire file/program. ([Location 530](https://readwise.io/to_kindle?action=open&asin=B084BNMN7T&location=530))
- Tags: [[blue]]
- Almost every website (web application) you use is comprised of many different JS files (typically with the .js file extension). It’s tempting to think of the whole thing (the application) as one program. But JS sees it differently. In JS, each standalone file is its own separate program. The reason this matters is primarily around error handling. Since JS treats files as programs, one file may fail (during parse/compile or execution) and that will not necessarily prevent the next file from being processed. ([Location 563](https://readwise.io/to_kindle?action=open&asin=B084BNMN7T&location=563))
- Tags: [[blue]]
- It’s important to ensure that each file works properly, and that to whatever extent possible, they handle failure in other files as gracefully as possible. ([Location 568](https://readwise.io/to_kindle?action=open&asin=B084BNMN7T&location=568))
- The only way multiple standalone .js files act as a single program is by sharing their state (and access to their public functionality) via the “global scope.” They mix together in this global scope namespace, so at runtime they act as as whole. ([Location 574](https://readwise.io/to_kindle?action=open&asin=B084BNMN7T&location=574))
- Tags: [[blue]]
- Regardless of which code organization pattern (and loading mechanism) is used for a file (standalone or module), you should still think of each file as its own (mini) program, which may then cooperate with other (mini) programs to perform the functions of your overall application. ([Location 581](https://readwise.io/to_kindle?action=open&asin=B084BNMN7T&location=581))
- Tags: [[blue]]
- The better approach is to use " or ' (again, pick one and stick to it!) for strings unless you need interpolation; reserve ` only for strings that will include interpolated expressions. ([Location 607](https://readwise.io/to_kindle?action=open&asin=B084BNMN7T&location=607))
- Tags: [[blue]]
- it’s safest and best to use only undefined as the single empty value, ([Location 630](https://readwise.io/to_kindle?action=open&asin=B084BNMN7T&location=630))
- Tags: [[blue]]
- JS arrays can hold any value type, either primitive or object (including other arrays). ([Location 650](https://readwise.io/to_kindle?action=open&asin=B084BNMN7T&location=650))
- Tags: [[blue]]
- Objects are more general: an unordered, keyed collection of any various values. In other words, you access the element by a string location name (aka “key” or “property”) rather than by its numeric position (as with arrays). ([Location 654](https://readwise.io/to_kindle?action=open&asin=B084BNMN7T&location=654))
- Tags: [[blue]]
- typeof null unfortunately returns "object" instead of the expected "null". Also, typeof returns the specific "function" for functions, but not the expected "array" for arrays. ([Location 685](https://readwise.io/to_kindle?action=open&asin=B084BNMN7T&location=685))
- Tags: [[blue]]
- Converting from one value type to another, such as from string to number, is referred to in JS as “coercion.” ([Location 687](https://readwise.io/to_kindle?action=open&asin=B084BNMN7T&location=687))
- Tags: [[blue]]
- The let keyword has some differences to var, with the most obvious being that let allows a more limited access to the variable than var. This is called “block scoping” as opposed to regular or function scoping. ([Location 703](https://readwise.io/to_kindle?action=open&asin=B084BNMN7T&location=703))
- Tags: [[blue]]
- Block-scoping is very useful for limiting how widespread variable declarations are in our programs, which helps prevent accidental overlap of their names. ([Location 716](https://readwise.io/to_kindle?action=open&asin=B084BNMN7T&location=716))
- Tags: [[blue]]
- It’s very common to suggest that var should be avoided in favor of let (or const!), generally because of perceived confusion over how the scoping behavior of var has worked since the beginning of JS. I believe this to be overly restrictive advice and ultimately unhelpful. It’s assuming you are unable to learn and use a feature properly in combination with other features. I believe you can and should learn any features available, and use them where appropriate! ([Location 720](https://readwise.io/to_kindle?action=open&asin=B084BNMN7T&location=720))
- Tags: [[blue]]
- A third declaration form is const. It’s like let but has an additional limitation that it must be given a value at the moment it’s declared, and cannot be re-assigned a different value later. ([Location 724](https://readwise.io/to_kindle?action=open&asin=B084BNMN7T&location=724))
- Tags: [[blue]]
- It’s ill-advised to use const with object values, because those values can still be changed even though the variable can’t be re-assigned. This leads to potential confusion down the line, ([Location 736](https://readwise.io/to_kindle?action=open&asin=B084BNMN7T&location=736))
- Tags: [[blue]]
- The best semantic use of a const is when you have a simple primitive value that you want to give a useful name to, such as using myBirthday instead of true. This makes programs easier to read. ([Location 744](https://readwise.io/to_kindle?action=open&asin=B084BNMN7T&location=744))
- Tags: [[blue]]
- If you stick to using const only with primitive values, you avoid any confusion of re-assignment (not allowed) vs. mutation (allowed)! That’s the safest and best way to use const. ([Location 747](https://readwise.io/to_kindle?action=open&asin=B084BNMN7T&location=747))
- Tags: [[blue]]
- It’s extremely important to note that in JS, functions are values that can be assigned (as shown in this snippet) and passed around. In fact, JS functions are a special type of the object value type. Not all languages treat functions as values, but it’s essential for a language to support the functional programming pattern, as JS does. ([Location 783](https://readwise.io/to_kindle?action=open&asin=B084BNMN7T&location=783))
- Tags: [[blue]]
- Since functions are values, they can be assigned as properties on objects: ([Location 803](https://readwise.io/to_kindle?action=open&asin=B084BNMN7T&location=803))
- Tags: [[blue]]
- Another way ===’s equality comparison is often described is, “checking both the value and the type”. In several of the examples we’ve looked at so far, like 42 === "42", the type of both values (number, string, etc.) does seem to be the distinguishing factor. There’s more to it than that, though. All value comparisons in JS consider the type of the values being compared, not just the === operator. Specifically, === disallows any sort of type conversion (aka, “coercion”) in its comparison, where other JS comparisons do allow coercion. ([Location 848](https://readwise.io/to_kindle?action=open&asin=B084BNMN7T&location=848))
- Tags: [[blue]]
- But the === operator does have some nuance to it, a fact many JS developers gloss over, to their detriment. The === operator is designed to lie in two cases of special values: NaN and -0. Consider: NaN === NaN; // false 0 === -0; // true In the case of NaN, the === operator lies and says that an occurrence of NaN is not equal to another NaN. In the case of -0 (yes, this is a real, distinct value you can use intentionally in your programs!), the === operator lies and says it’s equal to the regular 0 value. ([Location 853](https://readwise.io/to_kindle?action=open&asin=B084BNMN7T&location=853))
- For NaN comparisons, use the Number.isNaN(..) utility, which does not lie. For -0 comparison, use the Object.is(..) utility, which also does not lie. Object.is(..) can also be used for non-lying NaN checks, if you prefer. Humorously, you could think of Object.is(..) as the “quadruple-equals” ====, the really-really-strict comparison! ([Location 864](https://readwise.io/to_kindle?action=open&asin=B084BNMN7T&location=864))
- Tags: [[blue]]
- It may seem reasonable to assume that an equality check considers the nature or contents of the value; after all, 42 === 42 considers the actual 42 value and compares it. But when it comes to objects, a content-aware comparison is generally referred to as “structural equality.” JS does not define === as structural equality for object values. Instead, === uses identity equality for object values. ([Location 882](https://readwise.io/to_kindle?action=open&asin=B084BNMN7T&location=882))
- Tags: [[blue]]
- In JS, all object values are held by reference (see “Values vs References” in Appendix A), are assigned and passed by reference-copy, and to our current discussion, are compared by reference (identity) equality. Consider: ([Location 885](https://readwise.io/to_kindle?action=open&asin=B084BNMN7T&location=885))
- var x = [ 1, 2, 3 ]; // assignment is by reference-copy, so // y references the *same* array as x, // not another copy of it. var y = x; y === x; // true y === [ 1, 2, 3 ]; // false x === [ 1, 2, 3 ]; // false In this snippet, y === x is true because both variables hold a reference to the same initial array. But the === [1,2,3] comparisons both fail because y and x, respectively, are being compared to new different arrays [1,2,3]. The array structure and contents don’t matter in this comparison, only the reference identity. ([Location 888](https://readwise.io/to_kindle?action=open&asin=B084BNMN7T&location=888))
- Tags: [[blue]]
- But beware, it’s more complicated than you’ll assume. For example, how might you determine if two function references are “structurally equivalent”? Even stringifying to compare their source code text wouldn’t take into account things like closure. JS doesn’t provide structural equality comparison because it’s almost intractable to handle all the corner cases! ([Location 905](https://readwise.io/to_kindle?action=open&asin=B084BNMN7T&location=905))
- Tags: [[blue]]
- The == operator performs an equality comparison similarly to how the === performs it. In fact, both operators consider the type of the values being compared. And if the comparison is between the same value type, both == and === do exactly the same thing, no difference whatsoever. If the value types being compared are different, the == differs from === in that it allows coercion before the comparison. In other words, they both want to compare values of like types, but == allows type conversions first, and once the types have been converted to be the same on both sides, then == does the same thing as ===. Instead of “loose equality,” the == operator should be described as “coercive equality.” ([Location 916](https://readwise.io/to_kindle?action=open&asin=B084BNMN7T&location=916))
- Tags: [[blue]]
- The wiser approach is not to avoid coercive comparisons, but to embrace and learn their ins and outs. Coercive comparisons crop up in other places in JS, such as conditionals ([Location 958](https://readwise.io/to_kindle?action=open&asin=B084BNMN7T&location=958))
- Tags: [[blue]]
- Two major patterns for organizing code (data and behavior) are used broadly across the JS ecosystem: classes and modules. These patterns are not mutually exclusive; many programs can and do use both. Other programs will stick with just one pattern, or even neither! ([Location 961](https://readwise.io/to_kindle?action=open&asin=B084BNMN7T&location=961))
- Tags: [[blue]]
- The fact that both the inherited and overridden methods can have the same name and co-exist is called polymorphism. ([Location 1075](https://readwise.io/to_kindle?action=open&asin=B084BNMN7T&location=1075))
- Tags: [[blue]]
- The module pattern has essentially the same goal as the class pattern, which is to group data and behavior together into logical units. Also like classes, modules can “include” or “access” the data and behaviors of other modules, for cooperation's sake. But modules have some important differences from classes. Most notably, the syntax is entirely different. ([Location 1078](https://readwise.io/to_kindle?action=open&asin=B084BNMN7T&location=1078))
- Tags: [[blue]]
- The key hallmarks of a classic module are an outer function (that runs at least once), which returns an “instance” of the module with one or more functions exposed that can operate on the module instance’s internal (hidden) data. Because a module of this form is just a function, and calling it produces an “instance” of the module, another description for these functions is “module factories”. ([Location 1083](https://readwise.io/to_kindle?action=open&asin=B084BNMN7T&location=1083))
- Tags: [[blue]]
- The class form stores methods and data on an object instance, which must be accessed with the this. prefix. With modules, the methods and data are accessed as identifier variables in scope, without any this. prefix. ([Location 1126](https://readwise.io/to_kindle?action=open&asin=B084BNMN7T&location=1126))
- Tags: [[blue]]
- First, there’s no wrapping function to define a module. The wrapping context is a file. ESMs are always file-based; one file, one module. Second, you don’t interact with a module’s “API” explicitly, but rather use the export keyword to add a variable or method to its public API definition. If something is defined in a module but not exported, then it stays hidden (just as with classic modules). Third, and maybe most noticeably different from previously discussed patterns, you don’t “instantiate” an ES module, you just import it to use its single instance. ESMs are, in effect, “singletons,” in that there’s only one instance ever created, at first import in your program, and all other imports just receive a reference to that same single instance. If your module needs to support multiple instantiations, you have to provide a classic module-style factory function on your ESM definition for that purpose. ([Location 1155](https://readwise.io/to_kindle?action=open&asin=B084BNMN7T&location=1155))
- Tags: [[blue]]
- The iterator pattern has been around for decades, and suggests a “standardized” approach to consuming data from a source one chunk at a time. The idea is that it’s more common and helpful to iterate the data source—to progressively handle the collection of data by processing the first part, then the next, and so on, rather than handling the entire set all at once. ([Location 1232](https://readwise.io/to_kindle?action=open&asin=B084BNMN7T&location=1232))
- Tags: [[blue]]
- The iterator pattern defines a data structure called an “iterator” that has a reference to an underlying data source (like the query result rows), which exposes a method like next(). Calling next() returns the next piece of data (i.e., a “record” or “row” from a database query). You don’t always know how many pieces of data that you will need to iterate through, so the pattern typically indicates completion by some special value or exception once you iterate through the entire set and go past the end. ([Location 1239](https://readwise.io/to_kindle?action=open&asin=B084BNMN7T&location=1239))
- Tags: [[blue]]
- Another mechanism that’s often used for consuming iterators is the ... operator. This operator actually has two symmetrical forms: spread and rest (or gather, as I prefer). The spread form is an iterator-consumer. To spread an iterator, you have to have something to spread it into. There are two possibilities in JS: an array or an argument list for a function call. ([Location 1263](https://readwise.io/to_kindle?action=open&asin=B084BNMN7T&location=1263))
- Tags: [[blue]]
- So where do we find iterables? ES6 defined the basic data structure/collection types in JS as iterables. This includes strings, arrays, maps, sets, and others. ([Location 1281](https://readwise.io/to_kindle?action=open&asin=B084BNMN7T&location=1281))
- Tags: [[blue]]
- Since arrays are iterables, we can shallow-copy an array using iterator consumption via the ... spread operator: var arrCopy = [ ...arr ]; ([Location 1292](https://readwise.io/to_kindle?action=open&asin=B084BNMN7T&location=1292))
- Tags: [[blue]]
- A Map data structure uses objects as keys, associating a value (of any type) with that object. Maps have a different default iteration than seen here, in that the iteration is not just over the map’s values but instead its entries. An entry is a tuple (2-element array) including both a key and a value. ([Location 1302](https://readwise.io/to_kindle?action=open&asin=B084BNMN7T&location=1302))
- Tags: [[blue]]
- For the most part, all built-in iterables in JS have three iterator forms available: keys-only (keys()), values-only (values()), and entries (entries()). ([Location 1338](https://readwise.io/to_kindle?action=open&asin=B084BNMN7T&location=1338))
- Tags: [[blue]]
- Beyond just using built-in iterables, you can also ensure your own data structures adhere to the iteration protocol; doing so means you opt into the ability to consume your data with for..of loops and the ... operator. “Standardizing” on this protocol means code that is overall more readily recognizable and readable. ([Location 1340](https://readwise.io/to_kindle?action=open&asin=B084BNMN7T&location=1340))
- Closure is when a function remembers and continues to access variables from outside its scope, even when the function is executed in a different scope. ([Location 1353](https://readwise.io/to_kindle?action=open&asin=B084BNMN7T&location=1353))
- When the greeting(..) function finishes running, normally we would expect all of its variables to be garbage collected (removed from memory). We’d expect each msg to go away, but they don’t. The reason is closure. Since the inner function instances are still alive (assigned to hello and howdy, respectively), their closures are still preserving the msg variables. These closures are not a snapshot of the msg variable’s value; they are a direct link and preservation of the variable itself. That means closure can actually observe (or make!) updates to these variables over time. ([Location 1375](https://readwise.io/to_kindle?action=open&asin=B084BNMN7T&location=1375))
- Tags: [[blue]]
- functions also have another characteristic besides their scope that influences what they can access. This characteristic is best described as an execution context, and it’s exposed to the function via its this keyword. ([Location 1433](https://readwise.io/to_kindle?action=open&asin=B084BNMN7T&location=1433))
- Tags: [[blue]]
- Scope is static and contains a fixed set of variables available at the moment and location you define a function, but a function’s execution context is dynamic, entirely dependent on how it is called (regardless of where it is defined or even called from). this is not a fixed characteristic of a function based on the function’s definition, but rather a dynamic characteristic that’s determined each time the function is called. ([Location 1435](https://readwise.io/to_kindle?action=open&asin=B084BNMN7T&location=1435))
- As there is no global variable named topic (and thus no such property on the global object), this.topic resolves to undefined. ([Location 1463](https://readwise.io/to_kindle?action=open&asin=B084BNMN7T&location=1463))
- Now consider: var homework = { topic: "JS", assignment: assignment }; homework.assignment(); // Kyle says to study JS A copy of the assignment function reference is set as a property on the homework object, and then it’s called as homework.assignment(). That means the this for that function call will be the homework object. Hence, this.topic resolves to "JS". ([Location 1464](https://readwise.io/to_kindle?action=open&asin=B084BNMN7T&location=1464))
- Tags: [[blue]]
- Lastly: var otherHomework = { topic: "Math" }; assignment.call(otherHomework); // Kyle says to study Math A third way to invoke a function is with the call(..) method, which takes an object (otherHomework here) to use for setting the this reference for the function call. The property reference this.topic resolves to "Math". ([Location 1472](https://readwise.io/to_kindle?action=open&asin=B084BNMN7T&location=1472))
- The benefit of this-aware functions—and their dynamic context—is the ability to more flexibly re-use a single function with data from different objects. A function that closes over a scope can never reference a different scope or set of variables. But a function that has dynamic this context awareness can be quite helpful for certain tasks. ([Location 1480](https://readwise.io/to_kindle?action=open&asin=B084BNMN7T&location=1480))
- Tags: [[blue]]
- Where this is a characteristic of function execution, a prototype is a characteristic of an object, and specifically resolution of a property access. Think about a prototype as a linkage between two objects; the linkage is hidden behind the scenes, though there are ways to expose and observe it. This prototype linkage occurs when an object is created; it’s linked to another object that already exists. ([Location 1483](https://readwise.io/to_kindle?action=open&asin=B084BNMN7T&location=1483))
- Tags: [[blue]]
- Consider defining an object as a normal literal: var homework = { topic: "JS" }; The homework object only has a single property on it: topic. However, its default prototype linkage connects to the Object.prototype object, which has common built-in methods on it like toString() and valueOf(), among others. ([Location 1489](https://readwise.io/to_kindle?action=open&asin=B084BNMN7T&location=1489))
- Tags: [[blue]]
- The organization of variables into units of scope (functions, blocks) is one of the most foundational characteristics of any language; perhaps no other characteristic has a greater impact on how programs behave. ([Location 1577](https://readwise.io/to_kindle?action=open&asin=B084BNMN7T&location=1577))
- Tags: [[blue]]
- Scopes are like buckets, and variables are like marbles you put into those buckets. The scope model of a language is like the rules that help you determine which color marbles go in which matching-color buckets. ([Location 1579](https://readwise.io/to_kindle?action=open&asin=B084BNMN7T&location=1579))
- Scopes nest inside each other, and for any given expression or statement, only variables at that level of scope nesting, or in higher/outer scopes, are accessible; variables from lower/inner scopes are hidden and inaccessible. ([Location 1581](https://readwise.io/to_kindle?action=open&asin=B084BNMN7T&location=1581))
- Tags: [[orange]]
- hoisting: when all variables declared anywhere in a scope are treated as if they’re declared at the beginning of the scope. The other is that var-declared variables are function scoped, even if they appear inside a block. ([Location 1587](https://readwise.io/to_kindle?action=open&asin=B084BNMN7T&location=1587))
- Tags: [[blue]]
- Closure is a natural result of lexical scope when the language has functions as first-class values, as JS does. When a function makes reference to variables from an outer scope, and that function is passed around as a value and executed in other scopes, it maintains access to its original scope variables; this is closure. ([Location 1592](https://readwise.io/to_kindle?action=open&asin=B084BNMN7T&location=1592))
- Tags: [[blue]]
- another approach, in a very different direction, is to simply embrace objects as objects, forget classes altogether, and let objects cooperate through the prototype chain. This is called behavior delegation. I think delegation is more powerful than class inheritance, as a means for organizing behavior and data in our programs. ([Location 1605](https://readwise.io/to_kindle?action=open&asin=B084BNMN7T&location=1605))
- Tags: [[blue]]
- Even if a name is inferred, it’s still an anonymous function. Why? Because the inferred name is a metadata string value, not an available identifier to refer to the function. An anonymous function doesn’t have an identifier to use to refer to itself from inside itself—for recursion, event unbinding, etc. ([Location 1740](https://readwise.io/to_kindle?action=open&asin=B084BNMN7T&location=1740))
- Tags: [[blue]]
- Keep in mind that arrow function expressions are syntactically anonymous, meaning the syntax doesn’t provide a way to provide a direct name identifier for the function. The function expression may get an inferred name, but only if it’s one of the assignment forms, not in the (more common!) form of being passed as a function call argument (as in the last line of the snippet). ([Location 1798](https://readwise.io/to_kindle?action=open&asin=B084BNMN7T&location=1798))
- Tags: [[blue]]
- Since I don’t think anonymous functions are a good idea to use frequently in your programs, I’m not a fan of using the => arrow function form. This kind of function actually has a specific purpose (i.e., handling the this keyword lexically), but that doesn’t mean we should use it for every function we write. Use the most appropriate tool for each job. ([Location 1801](https://readwise.io/to_kindle?action=open&asin=B084BNMN7T&location=1801))