Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

duplicate .editorconfig config, typo, sample code and grammar #1793

Open
wants to merge 2 commits into
base: 2nd-ed
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,3 @@ indent_size = 4

[*.md]
indent_style = space
indent_size = 4
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ However, if you choose to contribute content (not just typo corrections) to this

## Reading Experience (Chapter/Section links, etc)

I understand that reading one long .md file, with no relative cross links to other sections/etc, is not the preferred reading experience for most of you. As such, it's totally reasonable to want to file an issue/PR to add those kinds of features.
I understand that reading one long .md file, with no relative cross links to other sections/etc., is not the preferred reading experience for most of you. As such, it's totally reasonable to want to file an issue/PR to add those kinds of features.

This topic has been brought up many times, and I've considered it. For now, I **do not** accept these kinds of changes into the repo.

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ This edition of the books is being self-published through [GetiPub](https://geti

If you'd like to contribute financially towards the effort (or any of my other OSS efforts) aside from purchasing the published books, please consider these options:

* [Github Sponsorship](https://github.com/users/getify/sponsorship)
* [GitHub Sponsorship](https://github.com/users/getify/sponsorship)
* [Patreon](https://www.patreon.com/getify)
* [Paypal](https://www.paypal.me/getify)

Expand Down
2 changes: 1 addition & 1 deletion get-started/ch1.md
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ The original snippet relied on `let` to create block-scoped `x` variables in bot

| NOTE: |
| :--- |
| The `let` keyword was added in ES6 (in 2015). The preceding example of transpiling would only need to apply if an application needed to run in a pre-ES6 supporting JS environment. The example here is just for simplicity of illustration. When ES6 was new, the need for such a transpilation was quite prevalent, but in 2020 it's much less common to need to support pre-ES6 environments. The "target" used for transpiliation is thus a sliding window that shifts upward only as decisions are made for a site/application to stop supporting some old browser/engine. |
| The `let` keyword was added in ES6 (in 2015). The preceding example of transpiling would only need to apply if an application needed to run in a pre-ES6 supporting JS environment. The example here is just for simplicity of illustration. When ES6 was new, the need for such a transpilation was quite prevalent, but in 2020 it's much less common to need to support pre-ES6 environments. The "target" used for transpilation is thus a sliding window that shifts upward only as decisions are made for a site/application to stop supporting some old browser/engine. |

You may wonder: why go to the trouble of using a tool to convert from a newer syntax version to an older one? Couldn't we just write the two variables and skip using the `let` keyword? The reason is, it's strongly recommended that developers use the latest version of JS so that their code is clean and communicates its ideas most effectively.

Expand Down
20 changes: 10 additions & 10 deletions objects-classes/ch1.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ The object mechanism is certainly the most flexible and powerful container type

Why are prototypes so core to JS as to be one of its three pillars? Among other things, prototypes are how JS's object system can express the class design pattern, one of the most widely relied on design patterns in all of programming.

So our journey here will start with objects, build up a compelete understanding of prototypes, de-mystify the `this` keyword, and explore the `class` system.
So our journey here will start with objects, build up a complete understanding of prototypes, de-mystify the `this` keyword, and explore the `class` system.

## About This Book

Expand Down Expand Up @@ -143,7 +143,7 @@ The `42` property name will be treated as an integer property name (aka, index);
| :--- |
| If you need to actually use an object as a key/property name, never rely on this computed string coercion; its behavior is surprising and almost certainly not what's expected, so program bugs are likely to occur. Instead, use a more specialized data structure, called a `Map` (added in ES6), where objects used as property "names" are left as-is instead of being coerced to a string value. |

As with with `[myObj]` above, you can *compute* any **property name** (distinct from computing the property value) at the time of object literal definition:
As with `[myObj]` above, you can *compute* any **property name** (distinct from computing the property value) at the time of object literal definition:

```js
anotherObj = {
Expand Down Expand Up @@ -195,7 +195,7 @@ anotherObj = {

| NOTE: |
| :--- |
| That would have been the same thing as the quoted property name definition `"coolFact": coolFact`, but JS developers rarely quote property names unless strictly necessary. Indeed, it's idiomatic to avoid the quotes unless required, so it's discouraged to include them unneccessarily. |
| That would have been the same thing as the quoted property name definition `"coolFact": coolFact`, but JS developers rarely quote property names unless strictly necessary. Indeed, it's idiomatic to avoid the quotes unless required, so it's discouraged to include them unnecessarily. |

In this situation, where the property name and value expression identifier are identical, you can omit the property-name portion of the property definition, as a so-called "concise property" definition:

Expand Down Expand Up @@ -365,7 +365,7 @@ Object.entries(myObj);
// [ ["favoriteNumber",42], ["isDeveloper",true], ["firstName","Kyle"] ]
```

Added in ES6, `Object.entries(..)` retieves this list of entries -- containing only owned an enumerable properties; see the "Property Descriptors" section in the next chapter -- from a source object.
Added in ES6, `Object.entries(..)` retrieves this list of entries -- containing only owned an enumerable properties; see the "Property Descriptors" section in the next chapter -- from a source object.

Such a list can be looped/iterated over, potentially assigning properties to another existing object. However, it's also possible to create a new object from a list of entries, using `Object.fromEntries(..)` (added in ES2019):

Expand All @@ -380,7 +380,7 @@ myObjShallowCopy = Object.fromEntries( Object.entries(myObj) );

Another approach to accessing properties is through object destructuring (added in ES6). Think of destructuring as defining a "pattern" that describes what an object value is supposed to "look like" (structurally), and then asking JS to follow that "pattern" to systematically access the contents of an object value.

The end result of object destructuring is not another object, but rather one or more assignments to other targets (variables, etc) of the values from the source object.
The end result of object destructuring is not another object, but rather one or more assignments to other targets (variables, etc.) of the values from the source object.

Imagine this sort of pre-ES6 code:

Expand Down Expand Up @@ -526,7 +526,7 @@ Note that `null` and `undefined` can be object-ified, by calling `Object(null)`
| :--- |
| Boxing has a counterpart: unboxing. For example, the JS engine will take an object wrapper -- like a `Number` object wrapped around `42` -- created with `Number(42)` or `Object(42)` -- and unwrap it to retrieve the underlying primitive `42`, whenever a mathematical operation (like `*` or `-`) encounters such an object. Unboxing behavior is way out of scope for our discussion, but is covered fully in the aforementioned "Types & Grammar" title. |

## Assiging Properties
## Assigning Properties

Whether a property is defined at the time of object literal definition, or added later, the assignment of a property value is done with the `=` operator, as any other normal assignment would be:

Expand Down Expand Up @@ -644,9 +644,9 @@ There's a variety of other mechanisms available, as well. `Object.keys(..)` give

But what if we wanted to get *all* the keys in an object (enumerable or not)? `Object.getOwnPropertyNames(..)` seems to do what we want, in that it's like `Object.keys(..)` but also returns non-enumerable property names. However, this list **will not** include any Symbol property names, as those are treated as special locations on the object. `Object.getOwnPropertySymbols(..)` returns all of an object's Symbol properties. So if you concatenate both of those lists together, you'd have all the direct (*owned*) contents of an object.

Yet as we've implied several times already, and will cover in full detail in the next chapter, an object also can also "inherit" contents from its `[[Prototype]]` chain. These are not considered *owned* contents, so they won't show up in any of these lists.
Yet as we've implied several times already, and will cover in full detail in the next chapter, an object also can "inherit" contents from its `[[Prototype]]` chain. These are not considered *owned* contents, so they won't show up in any of these lists.

Recall that the `in` operator will potentially traverse the entire chain looking for the existence of a property. Similarly, a `for..in` loop will traverse the chain and list any enumerable (owned or inhertied) properties. But there's no built-in API that will traverse the whole chain and return a list of the combined set of both *owned* and *inherited* contents.
Recall that the `in` operator will potentially traverse the entire chain looking for the existence of a property. Similarly, a `for..in` loop will traverse the chain and list any enumerable (owned or inherited) properties. But there's no built-in API that will traverse the whole chain and return a list of the combined set of both *owned* and *inherited* contents.

## Temporary Containers

Expand Down Expand Up @@ -679,7 +679,7 @@ const { one, two, three } =
// transport for multiple input values
formatValues({
one: "Kyle",
two: "Simpson"
two: "Simpson",
three: "getify"
});

Expand All @@ -699,7 +699,7 @@ The most common usage of objects is as containers for multiple values. We create
* defining properties (named locations), either at object creation time or later
* assigning values, either at object creation time or later
* accessing values later, using the location names (property names)
* deleteing properties via `delete`
* deleting properties via `delete`
* determining container contents with `in`, `hasOwnProperty(..)` / `hasOwn(..)`, `Object.entries(..)` / `Object.keys(..)`, etc

But there's a lot more to objects than just static collections of property names and values. In the next chapter, we'll dive under the hood to look at how they actually work.
Expand Down
4 changes: 2 additions & 2 deletions objects-classes/ch2.md
Original file line number Diff line number Diff line change
Expand Up @@ -191,13 +191,13 @@ myList; // [ 23, 42, 109, empty x 11, "Hello" ]
myList[9]; // undefined
```

You might wonder why empty slots are so bad? One reason: there are APIs in JS, like array's `map(..)`, where empty slots are suprisingly skipped over! Never, ever intentionally create empty slots in your arrays. This in undebateably one of JS's "bad parts".
You might wonder why empty slots are so bad? One reason: there are APIs in JS, like array's `map(..)`, where empty slots are surprisingly skipped over! Never, ever intentionally create empty slots in your arrays. This in undebateably one of JS's "bad parts".

### Functions

I don't have much specifically to say about functions here, other than to point out that they are also sub-object-types. This means that in addition to being executable, they can also have named properties added to or accessed from them.

Functions have two pre-defined properties you may find yourself interacting with, specifially for meta-programming purposes:
Functions have two pre-defined properties you may find yourself interacting with, specifically for meta-programming purposes:

```js
function help(opt1,opt2,...remainingOpts) {
Expand Down
6 changes: 3 additions & 3 deletions scope-closures/apA.md
Original file line number Diff line number Diff line change
Expand Up @@ -382,7 +382,7 @@ Briefly: arrow functions don't define a `this` identifier keyword at all. If you

In other words, arrow functions treat `this` like any other lexical variable.

If you're used to hacks like `var self = this`, or if you prefer to call `.bind(this)` on inner `function` expressions, just to force them to inherit a `this` from an outer function like it was a lexical variable, then `=>` arrow functions are absolutely the better option. They're designed specifically to fix that problem.
If you're used to hack like `var self = this`, or if you prefer to call `.bind(this)` on inner `function` expressions, just to force them to inherit a `this` from an outer function like it was a lexical variable, then `=>` arrow functions are absolutely the better option. They're designed specifically to fix that problem.

So, in the rare cases you need *lexical this*, use an arrow function. It's the best tool for that job. But just be aware that in doing so, you're accepting the downsides of an anonymous function. You should expend additional effort to mitigate the readability *cost*, such as more descriptive variable names and code comments.

Expand Down Expand Up @@ -933,7 +933,7 @@ The latter one is definitely not an example of closure, at least not in any usef

### Defer to Closure

By the way, Chapter 7 briefly mentioned partial application and currying (which *do* rely on closure!). This is a interesting scenario where manual currying can be used:
By the way, Chapter 7 briefly mentioned partial application and currying (which *do* rely on closure!). This is an interesting scenario where manual currying can be used:

```js
function printLabels(labels) {
Expand Down Expand Up @@ -1013,7 +1013,7 @@ But I strongly prefer, and always use myself, the former `publicAPI` form. Two r

Whatever the case may be, it just seems rather silly to me that we *wouldn't* maintain a reference to access our own API. Right?

### Asynchronous Module Defintion (AMD)
### Asynchronous Module Definition (AMD)

Another variation on the classic module form is AMD-style modules (popular several years back), such as those supported by the RequireJS utility:

Expand Down
2 changes: 1 addition & 1 deletion scope-closures/ch4.md
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,7 @@ function hello() {
hello();
// Hello, Kyle!

export hello;
export { hello };
```

If that code is in a file that's loaded as an ES module, it will still run exactly the same. However, the observable effects, from the overall application perspective, will be different.
Expand Down
2 changes: 1 addition & 1 deletion scope-closures/ch5.md
Original file line number Diff line number Diff line change
Expand Up @@ -524,7 +524,7 @@ console.log(studentName);

Remember that we've asserted a few times so far that *Compiler* ends up removing any `var`/`let`/`const` declarators, replacing them with the instructions at the top of each scope to register the appropriate identifiers.

So if we analyze what's going on here, we see that an additional nuance is that *Compiler* is also adding an instruction in the middle of the program, at the point where the variable `studentName` was declared, to handle that declaration's auto-initialization. We cannot use the variable at any point prior to that initialization occuring. The same goes for `const` as it does for `let`.
So if we analyze what's going on here, we see that an additional nuance is that *Compiler* is also adding an instruction in the middle of the program, at the point where the variable `studentName` was declared, to handle that declaration's auto-initialization. We cannot use the variable at any point prior to that initialization occurring. The same goes for `const` as it does for `let`.

The term coined by TC39 to refer to this *period of time* from the entering of a scope to where the auto-initialization of the variable occurs is: Temporal Dead Zone (TDZ).

Expand Down