From 9989387c84feba59f17996e1e478c238731882f3 Mon Sep 17 00:00:00 2001 From: chewiebug Date: Tue, 22 Aug 2017 22:55:06 +0200 Subject: [PATCH 01/23] fix syntax error (#42) --- ch04.asciidoc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ch04.asciidoc b/ch04.asciidoc index 6342cf1..2bf7279 100644 --- a/ch04.asciidoc +++ b/ch04.asciidoc @@ -1699,8 +1699,8 @@ As a bonus, we'll have `saveProducts` return a promise that's fulfilled after th [source,javascript] ---- saveProducts(function* () { - const p2 = yield '/products/modern-javascript' - const p2 = yield '/products/mastering-modular-javascript' + yield '/products/modern-javascript' + yield '/products/mastering-modular-javascript' return '/wishlists/books' }).then(response => { // continue after storing the product list From 0cf0c36ef302714845ab179b1d039a000c78eb2e Mon Sep 17 00:00:00 2001 From: Thiago Arrais Date: Mon, 2 Oct 2017 14:38:45 -0300 Subject: [PATCH 02/23] fix babel-preset-env version ref (#43) --- ch01.asciidoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ch01.asciidoc b/ch01.asciidoc index 5ffb286..93701bc 100644 --- a/ch01.asciidoc +++ b/ch01.asciidoc @@ -147,7 +147,7 @@ To install Babel, enter the following couple of commands into your favorite term [source,shell] ---- npm install babel-cli​@6 --save-dev -npm install babel-preset-env@6 --save-dev +npm install babel-preset-env@1 --save-dev ---- [NOTE] From 2180b4678085ed6bd181b9f301a777af7cc1efab Mon Sep 17 00:00:00 2001 From: Vse Mozhet Byt Date: Tue, 6 Feb 2018 16:13:49 +0200 Subject: [PATCH 03/23] fix another possible typo in preface (#47) --- preface.asciidoc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/preface.asciidoc b/preface.asciidoc index d713ca4..ae7195d 100644 --- a/preface.asciidoc +++ b/preface.asciidoc @@ -65,7 +65,7 @@ pass:[http://oreilly.com/safari]. +For more information, please visit pass:[http://oreilly.com/safari]. [role="pagebreak-before"] === How to Contact Us @@ -101,7 +101,7 @@ Watch us on YouTube: link:$$http://www.youtube.com/oreillymedia$$[] Like virtually every human task ever carried out, _Practical Modern JavaScript_ was made possible only by building upon the work of others. I want to thank Nan Barber, my editor at O'Reilly, for her fantastic support along the ride of writing this book. Ally MacDonald, another editor at O'Reilly, helped me out in the early days of the project and is the foremost reason why Modular JavaScript became a book series, as she helped me conjure up a modular approach to teaching JavaScript. -This book had a phenomenal ensemble of technical reviewers. Many of these folks are on TC39, the technical committee devoted to pushing JavaScript forward, and it's deeply humbling that they gave up some of their time to help future-proof this book. As always, Mathias Bynens (TC39, Google) proved instrumental to proofing everything in the book with regards to Unicode standards and held my work to a high degree of consistency in terms of code snippets. Kent C. Dodds (TC39, PayPal) ingeniously offered video reviews where he identified weak spots and helped improve the book. Jordan Harband (TC39, Airbnb) came through with deep technical commentary about many of the JavaScript features discussed in the book, and along with Alex Russell (TC39, Google) helped me iron out the history of JavaScript and its standards body for the first chapter. Ingvar Stepanyan (Cloudflare) was also a sharp eye in identifying code issues and pinpointed mistakes around low-level aspects of the specification. Brian Terlson (TC39 editor, Microsoft) also helped out with timelines and details around TC39. Rod Vagg (Node.js) provided insight that lead to better code examples and more consistent code style throughout the book. +This book had a phenomenal ensemble of technical reviewers. Many of these folks are on TC39, the technical committee devoted to pushing JavaScript forward, and it's deeply humbling that they gave up some of their time to help future-proof this book. As always, Mathias Bynens (TC39, Google) proved instrumental to proofing everything in the book with regards to Unicode standards and held my work to a high degree of consistency in terms of code snippets. Kent C. Dodds (TC39, PayPal) ingeniously offered video reviews where he identified weak spots and helped improve the book. Jordan Harband (TC39, Airbnb) came through with deep technical commentary about many of the JavaScript features discussed in the book, and along with Alex Russell (TC39, Google) helped me iron out the history of JavaScript and its standards body for the first chapter. Ingvar Stepanyan (Cloudflare) was also a sharp eye in identifying code issues and pinpointed mistakes around low-level aspects of the specification. Brian Terlson (TC39 editor, Microsoft) also helped out with timelines and details around TC39. Rod Vagg (Node.js) provided insight that led to better code examples and more consistent code style throughout the book. Brendan Eich (TC39, Brave CEO) provided a trove of insight into the early days of JavaScript and TC39, which proved essential to the development of the first chapter. And naturally, if not for him, you wouldn't be holding this book in your hands. From f419c0393fc982f2d5c8cfb08209b85be6810ecd Mon Sep 17 00:00:00 2001 From: Vse Mozhet Byt Date: Tue, 6 Feb 2018 16:14:39 +0200 Subject: [PATCH 04/23] fix possible typo in preface (#46) Object destructuring seems classic ES6, while object rest/spread properties are of the mentioned later additions. --- preface.asciidoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/preface.asciidoc b/preface.asciidoc index ae7195d..2719848 100644 --- a/preface.asciidoc +++ b/preface.asciidoc @@ -11,7 +11,7 @@ This book is meant for web developers, enthusiasts, and professionals with a wor The goal of this book is to provide an approachable way of learning the latest developments in JavaScript: ES6 and later. ES6 was a huge update to the language, and it came out around the same time as a streamlined specification development process. Around this time I wrote quite a few blog posts about the different features in ES6, which became a bit popular. There are quite a few other books on ES6 out there, but they're a little different from what I had in mind for a book on ES6 and beyond. This book tries to explain features in detail without getting caught up in the specification, its implementation details, or unlikely corner cases that would almost certainly need to be researched online if happened upon. -Instead of extreme thoroughness, the book places its utmost focus in the learning process, having sorted its material in such an incremental way that you don't have to scan ahead in the book for the definition of something else. Armed with practical examples, _Practical Modern JavaScript_ goes beyond ES6 to capture the changes to the language since June 2015--when the ES6 specification was finalized--including async functions, object destructuring, dynamic imports, `Promise#finally`, and async generators. +Instead of extreme thoroughness, the book places its utmost focus in the learning process, having sorted its material in such an incremental way that you don't have to scan ahead in the book for the definition of something else. Armed with practical examples, _Practical Modern JavaScript_ goes beyond ES6 to capture the changes to the language since June 2015--when the ES6 specification was finalized--including async functions, object rest/spread properties, dynamic imports, `Promise#finally`, and async generators. Lastly, this book has the goal of establishing a baseline we can take for granted in the rest of the Modular JavaScript series. After having learned the latest language features in this first book, we'll be all set to discuss modular design, testing, and deployment, without having to diverge into language features whenever they're used in a code example. This incremental and modular approach is meant to be pervasive across the series, each book, each chapter, and each section. From c50fd87ed59c3cdb16abae62853bb58cadac911e Mon Sep 17 00:00:00 2001 From: Vse Mozhet Byt Date: Mon, 19 Feb 2018 15:56:38 +0200 Subject: [PATCH 05/23] ch01: fix nit in ESLint --fix result example (#51) This error is mentioned in the screenshot above and is fixed in my local test run. --- ch01.asciidoc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ch01.asciidoc b/ch01.asciidoc index 93701bc..fedcc6a 100644 --- a/ch01.asciidoc +++ b/ch01.asciidoc @@ -85,7 +85,7 @@ Let's talk about how you can use Babel as part of your workflow. Babel can compile modern JavaScript code that relies on ES6 features into ES5. It produces human-readable code, making it more welcoming when we don't have a firm grasp on all of the new features we're using. -The online https://mjavascript.com/out/babel-repl[Babel REPL (Read-Evaluate-Print Loop)] is an excellent way of jumping right into learning ES6, without any of the hassle of installing Node.js and the `babel` CLI, and manually compiling source code. +The online https://mjavascript.com/out/babel-repl[Babel REPL (Read-Evaluate-Print Loop)] is an excellent way of jumping right into learning ES6, without any of the hassle of installing Node.js and the `babel` CLI, and manually compiling source code. The REPL provides us with a source code input area that gets automatically compiled in real time. We can see the compiled code to the right of our source code. @@ -311,7 +311,7 @@ When we run `lint-fix` we'll only get a pair of errors: `hello` is never used an ---- var goodbye = 'Goodbye!' -function hello() { +function hello () { return goodbye } From 437b1fa82f019cc3ca1313c56df6436b57e05802 Mon Sep 17 00:00:00 2001 From: Vse Mozhet Byt Date: Mon, 19 Feb 2018 15:56:52 +0200 Subject: [PATCH 06/23] ch01: upgrade ESLint version in advisable command (#52) --- ch01.asciidoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ch01.asciidoc b/ch01.asciidoc index fedcc6a..dfc7646 100644 --- a/ch01.asciidoc +++ b/ch01.asciidoc @@ -234,7 +234,7 @@ ESLint is a modern linter that packs several plugins, sporting different rules, [source,shell] ---- -npm install eslint@3 --save-dev +npm install eslint@4 --save-dev ---- Next, we need to configure ESLint. Since we installed `eslint` as a local dependency, we'll find its command-line tool in _node_modules/.bin_. Executing the following command will guide us through configuring ESLint for our project for the first time. To get started, indicate you want to use a popular style guide and choose Standard,footnoteref:[linters,Note that Standard is just a self-proclamation, and not actually standardized in any official capacity. It doesn't really matter which style guide you follow as long as you follow it consistently. Consistency helps reduce confusion while reading a project's codebase. The Airbnb style guide is also fairly popular and it doesn't omit semicolons by default, unlike Standard.] then pick JSON format for the configuration file: From a78153ace976a436e66d5e52d8fa0dc83c2a26a4 Mon Sep 17 00:00:00 2001 From: Thiago Arrais Date: Thu, 22 Feb 2018 22:30:52 -0300 Subject: [PATCH 07/23] fix typo (#53) --- ch09.asciidoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ch09.asciidoc b/ch09.asciidoc index 8b77039..bfdd181 100644 --- a/ch09.asciidoc +++ b/ch09.asciidoc @@ -802,7 +802,7 @@ const pistol = { caliber: 50, trigger() { setTimeout(() => { - console.log(`Fired caliber ${ self.caliber } pistol`) + console.log(`Fired caliber ${ this.caliber } pistol`) }, 1000) } } From 6eb381c8dbf7f1ae5624259bbe0f11fb03d7a573 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Bevacqua?= Date: Mon, 19 Mar 2018 00:47:06 -0300 Subject: [PATCH 08/23] fixes #54 (#55) --- ch02.asciidoc | 73 +++++++++++++++++++++++++-------------------------- 1 file changed, 36 insertions(+), 37 deletions(-) diff --git a/ch02.asciidoc b/ch02.asciidoc index 8bec1f8..8980ba0 100644 --- a/ch02.asciidoc +++ b/ch02.asciidoc @@ -401,70 +401,69 @@ This ((("arrow functions", startref="af2")))((("arrow functions", "merits and us ==== Destructuring Objects -Imagine ((("assignment destructuring", "objects", id="ad2o")))((("destructuring", "objects", id="d2o")))((("objects", "destructuring", id="o2d")))you had a program with some comic book characters, Bruce Wayne being one of them, and you want to refer to properties in the object that describes him. Here's the example object we'll be using for Batman: +Imagine ((("assignment destructuring", "objects", id="ad2o")))((("destructuring", "objects", id="d2o")))((("objects", "destructuring", id="o2d")))you had a program describing a color palette and you want to refer to properties in the object that describes it. Here's an example object we'll be using for our palette: [source,javascript] ---- -var character = { - name: 'Bruce', - pseudonym: 'Batman', - metadata: { - age: 34, - gender: 'male' +var palette = { + profile: 'intense-red', + name: 'Red', + color: { + code: `#f00` }, - batarang: ['gas pellet', 'bat-mobile control', 'bat-cuffs'] + luminosity: 0.8 } ---- -If you wanted a `pseudonym` variable referencing `character.pseudonym`, you could write the following bit of ES5 code. This is commonplace when, for instance, you'll be referencing `pseudonym` in several places in your codebase and you'd prefer to avoid typing out `character.pseudonym` each time: +If you wanted a `profile` variable referencing `palette.profile`, you could write the following bit of ES5 code. This is commonplace when, for instance, you'll be referencing `profile` in several places in your codebase and you'd prefer to avoid typing out `palette.profile` each time: [source,javascript] ---- -var pseudonym = character.pseudonym +var profile = palette.profile ---- -With destructuring in assignment, the syntax becomes a bit more clear. As you can see in the next example, you don't have to write `pseudonym` twice, while still clearly conveying intent. The following statement is equivalent to the previous one written in ES5 code: +With destructuring in assignment, the syntax becomes a bit more clear. As you can see in the next example, you don't have to write `profile` twice, while still clearly conveying intent. The following statement is equivalent to the previous one written in ES5 code: [source,javascript] ---- -var { pseudonym } = character +var { profile } = palette ---- Just like you could declare multiple comma-separated variables with a single `var` statement, you can also declare multiple variables within the curly braces of a destructuring expression: [source,javascript] ---- -var { pseudonym, name } = character +var { profile, name } = palette ---- In a similar fashion, you could mix and match destructuring with regular variable declarations in the same `var` statement. While this might look a bit confusing at first, it'll be up to any JavaScript coding style guides you follow to determine whether it's appropriate to declare several variables in a single statement. In any case, it goes to show the flexibility offered by destructuring syntax: [source,javascript] ---- -var { pseudonym } = character, two = 2 +var { profile } = palette, two = 2 ---- -If you want to extract a property named `pseudonym` but would like to declare it as a variable named `alias`, you can use the following destructuring syntax, known as _aliasing_. Note that you can use `alias` or any other valid variable name: +If you want to extract a property named `profile` but would like to declare it as a variable named `id`, you can use the following destructuring syntax, known as _aliasing_. Note that you can use `id` or any other valid variable name: [source,javascript] ---- -var { pseudonym: alias } = character -console.log(alias) -// <- 'Batman' +var { profile: id } = palette +console.log(id) +// <- 'intense-red' ---- -While aliases don't look any simpler than the ES5 flavor, `alias = character.pseudonym`, ((("aliases", id="al2")))they start making sense when you consider the fact that destructuring supports deep structures, as in the following example: +While aliases don't look any simpler than the ES5 flavor, `id = palette.profile`, ((("aliases", id="al2")))they start making sense when you consider the fact that destructuring supports deep structures, as in the following example: [source,javascript] ---- -var { metadata: { gender } } = character +var { color: { code } } = palette ---- In cases like the previous one, where you have deeply nested properties being destructured, you might be able to convey a property name more clearly if you choose an alias. Consider the next snippet, where a property named `code` wouldn't have been as indicative of its contents as `colorCode` could be: [source,javascript] ---- -var { metadata: { gender: characterGender } } = character +var { color: { code: colorCode } } = palette ---- The scenario we just saw repeats itself frequently, because properties are often named in the context of their host object. While `palette.color.code` is perfectly descriptive, `code` on its own could mean a wide variety of things, and aliases such as `colorCode` can help you bring context back into the variable name while still using destructuring. @@ -473,9 +472,9 @@ Whenever you access a nonexistent property in ES5 notation, you get a value of ` [source,javascript] ---- -console.log(character.boots) +console.log(palette.luminosity) // <- undefined -console.log(character['boots']) +console.log(palette['luminosity']) // <- undefined ---- @@ -483,8 +482,8 @@ With destructuring, the same behavior prevails. When declaring a destructured va [source,javascript] ---- -var { boots } = character -console.log(boots) +var { luminosity } = palette +console.log(luminosity) // <- undefined ---- @@ -492,7 +491,7 @@ A destructured declaration accessing a nested property of a parent object that's [source,javascript] ---- -var { boots: { size } } = character +var { stroke: { width } } = palette // <- Exception var { missing } = null // <- Exception @@ -511,37 +510,37 @@ As part of destructuring, you can provide default values for those cases where t [source,javascript] ---- -var { boots = { size: 10 } } = character -console.log(boots) -// <- { size: 10 } +var { description = 'This is a color palette' } = palette +console.log(description) +// <- 'This is a color palette' ---- Default values can also be provided in nested property destructuring. [source,javascript] ---- -var { metadata: { enemy = 'Satan' } } = character -console.log(enemy) -// <- 'Satan' +var { color: { density = 320 } } = palette +console.log(density) +// <- 320 ---- For use in combination with aliases, you should place the alias first, and then the default value, as shown next. [source,javascript] ---- -var { boots: footwear = { size: 10 } } = character +var { color: paletteColor = { density: 320 } } = palette ---- -It's possible to use the ((("computed property names")))computed property names syntax in destructuring patterns. In this case, however, you're required to provide an alias to be used as the variable name. That's because computed property names allow arbitrary expressions and thus the compiler wouldn't be able to infer a variable name. In the following example we use the `value` alias, and a computed property name to extract the `boots` property from the `character` object. +It's possible to use the ((("computed property names")))computed property names syntax in destructuring patterns. In this case, however, you're required to provide an alias to be used as the variable name. That's because computed property names allow arbitrary expressions and thus the compiler wouldn't be able to infer a variable name. In the following example we use the `paletteProfile` alias, and a computed property name to extract the `profile` property from the `palette` object. [source,javascript] ---- -var { ['boo' + 'ts']: characterBoots } = character -console.log(characterBoots) +var { ['pro' + 'file']: paletteProfile } = palette +console.log(paletteProfile) // <- true ---- -This flavor of destructuring is probably the least useful, as `characterBoots = character[type]` is usually simpler than `{ [type]: characterBoots } = character`, as it's a more sequential statement. That being said, the feature is useful when you have properties you want to declare in the object literal, as opposed to using subsequent assignment statements. +This flavor of destructuring is probably the least useful, as `sourceProperty = source[property]` is usually simpler than `{ [property]: sourceProperty } = source`, as it's a more sequential statement. That being said, the feature is useful when you have properties you want to declare in the object literal, as opposed to using subsequent assignment statements. That's it, as far as objects go, in terms of destructuring. ((("assignment destructuring", "objects", startref="ad2o")))((("destructuring", "objects", startref="d2o")))((("objects", "destructuring", startref="o2d")))((("aliases", startref="al2")))What about arrays? From d0cc54491325e0c2b8de0cf2320cdf4159c9954a Mon Sep 17 00:00:00 2001 From: Vse Mozhet Byt Date: Sun, 25 Mar 2018 22:29:48 +0300 Subject: [PATCH 09/23] ch02: fix possible typo in destructuring use case (#56) --- ch02.asciidoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ch02.asciidoc b/ch02.asciidoc index 8980ba0..4717cd8 100644 --- a/ch02.asciidoc +++ b/ch02.asciidoc @@ -745,7 +745,7 @@ console.log(random({ max: 24 })) // <- 18 ---- -Regular ((("assignment destructuring", "function parameters", startref="ad2fpd")))((("destructuring", "function parameters", startref="d2fpd")))((("function parameters", startref="fpd2")))expressions are another great fit for destructuring. Destructuring empowers you to name groups from a match without having to resort to index numbers. Here's an example `RegExp` that could be used for parsing simple dates, and an example of destructuring those dates into each of their components. The first entry in the resulting array is reserved for the raw input string, and we can discard it. +Regular ((("assignment destructuring", "function parameters", startref="ad2fpd")))((("destructuring", "function parameters", startref="d2fpd")))((("function parameters", startref="fpd2")))expressions are another great fit for destructuring. Destructuring empowers you to name groups from a match without having to resort to index numbers. Here's an example `RegExp` that could be used for parsing simple dates, and an example of destructuring those dates into each of their components. The first entry in the resulting array is reserved for the full matched text, and we can discard it. [source,javascript] ---- From 6b9308eb5ad8436f6e8496da6a30625d56d53039 Mon Sep 17 00:00:00 2001 From: Vse Mozhet Byt Date: Wed, 4 Apr 2018 04:36:56 +0300 Subject: [PATCH 10/23] ch02: fix typos in tagged templates examples (#58) --- ch02.asciidoc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ch02.asciidoc b/ch02.asciidoc index 4717cd8..39c8ec3 100644 --- a/ch02.asciidoc +++ b/ch02.asciidoc @@ -1185,7 +1185,7 @@ var name = 'Maurice' var emotion = 'thrilled' var text = tag`Hello, ${ name }. I am ${ emotion } to meet you!` console.log(text) -// <- 'Hello Maurice, I am thrilled to meet you!' +// <- 'Hello, Maurice. I am thrilled to meet you!' ---- Multiple use cases apply to tagged templates. One possible use case might be to make user input uppercase, making the string sound satirical. That's what the following piece of code does. We've modified `tag` slightly so that any interpolated strings are uppercased. @@ -1200,7 +1200,7 @@ function upper(parts, ...values) { var name = 'Maurice' var emotion = 'thrilled' upper`Hello, ${ name }. I am ${ emotion } to meet you!` -// <- 'Hello MAURICE, I am THRILLED to meet you!' +// <- 'Hello, MAURICE. I am THRILLED to meet you!' ---- A decidedly more useful use case would be to sanitize expressions interpolated into your templates, automatically, using a tagged template. Given a template where all expressions are considered user input, we could use a hypothetical `sanitize` library to remove HTML tags and similar hazards, preventing cross-site scripting (XSS) attacks where users might inject malicious HTML into our websites. From d2b2f17df31dce60aac61038bb6902e54e14e53c Mon Sep 17 00:00:00 2001 From: Vse Mozhet Byt Date: Wed, 4 Apr 2018 04:37:21 +0300 Subject: [PATCH 11/23] ch02: fix typos in multiline templates example (#57) --- ch02.asciidoc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ch02.asciidoc b/ch02.asciidoc index 39c8ec3..575f16c 100644 --- a/ch02.asciidoc +++ b/ch02.asciidoc @@ -1033,8 +1033,8 @@ A second line\n\ Then a third line' var concatenated = -'The first line\n' ` -'A second line\n' ` +'The first line\n' + +'A second line\n' + 'Then a third line' var joined = [ From caac11bd2b2a6f9df4f6562b7dd3922e14d2f9fe Mon Sep 17 00:00:00 2001 From: Vse Mozhet Byt Date: Wed, 2 May 2018 02:21:31 +0300 Subject: [PATCH 12/23] ch03: fix possibly outdated note (#59) --- ch03.asciidoc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ch03.asciidoc b/ch03.asciidoc index ca29f8f..39e81d2 100644 --- a/ch03.asciidoc +++ b/ch03.asciidoc @@ -337,7 +337,7 @@ class Plum extends createJuicyFruit('plum', 30) { } ---- -Let's move ((("prototypal inheritance", startref="pi3)))onto `Symbol`. While not an iteration or flow control mechanism, learning about `Symbol` is crucial to shaping an understanding of iteration protocols, which are discussed at length later in ((("classes", startref="class3")))((("classes", "extending", startref="class3ext")))the chapter. +Let's move ((("prototypal inheritance", startref="pi3)))onto `Symbol`. While not an iteration or flow control mechanism, learning about `Symbol` is crucial to shaping an understanding of iteration protocols, which are discussed at length in ((("classes", startref="class3")))((("classes", "extending", startref="class3ext")))the next chapter. === Symbols @@ -1043,7 +1043,7 @@ function getCommandProperties(ctor) { return [...properties] } getCommandProperties(Dog) -// <- [{ key: 'name', readLevel: 'game-master', +// <- [{ key: 'name', readLevel: 'game-master', // writeLevel: 'game-master' }] ---- From 0c1a5fac21d9506fd85460fa5a4cc6f7bcdda32b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Bevacqua?= Date: Sat, 9 Jun 2018 15:48:33 -0300 Subject: [PATCH 13/23] Fix #61 --- ch03.asciidoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ch03.asciidoc b/ch03.asciidoc index 39e81d2..7ea1100 100644 --- a/ch03.asciidoc +++ b/ch03.asciidoc @@ -771,7 +771,7 @@ Object.assign({}, { a: ['b', 'c', 'd'] }, { a: ['e', 'f'] }) // <- { a: ['e', 'f'] } ---- -At the time of this writing, there's an ECMAScript stage 3 proposalpass:[You can find the proposal draft at GitHub.] to implement spread in objects, similar to how you can spread iterable objects onto an array in ES6. Spreading an ((("objects", "object spread")))object onto another is equivalent to using an `Object.assign` function call. +At the time of this writing, there's an ECMAScript stage 3 proposalpass:[You can find the proposal draft at GitHub.] to implement spread in objects, similar to how you can spread iterable objects onto an array in ES6. Spreading an ((("objects", "object spread")))object onto another is equivalent to using an `Object.assign` function call. The following piece of code shows a few cases where we're spreading the properties of an object onto another one, and their `Object.assign` counterpart. As you can see, using object spread is more succinct and should be preferred where possible. From 8f45af735f80584bc42ad46e61b011cd7998de5f Mon Sep 17 00:00:00 2001 From: Vse Mozhet Byt Date: Sat, 9 Jun 2018 21:50:03 +0300 Subject: [PATCH 14/23] ch03: fix typos in Object.assign() section (#62) --- ch03.asciidoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ch03.asciidoc b/ch03.asciidoc index 7ea1100..efbdff5 100644 --- a/ch03.asciidoc +++ b/ch03.asciidoc @@ -755,7 +755,7 @@ console.log(Object.assign({}, defaults, options)) Note, however, that `Object.assign` doesn't cater to every need. While most user-land implementations have the ability to perform deep assignment, `Object.assign` doesn't offer a recursive treatment of objects. Object values are assigned as properties on `target` directly, instead of being recursively assigned key by key. -In the following bit of code you might expect the `f` property to be added to `target.a` while keeping `b.c` and `b.d` intact, but the `b.c` and `b.d` properties are lost when using `Object.assign`. +In the following bit of code you might expect the `f` property to be added to `target.a` while keeping `a.b` and `a.d` intact, but the `a.b` and `a.d` properties are lost when using `Object.assign`. [source,javascript] ---- From c48753b0582c86767dcbfa1d3d9b97bf89fef3bd Mon Sep 17 00:00:00 2001 From: Vse Mozhet Byt Date: Sat, 9 Jun 2018 22:02:22 +0300 Subject: [PATCH 15/23] ch3: fix typo in Object.setPrototypeOf() perf note (#63) Sync with the first sidebar paragraph and the source: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/setPrototypeOf --- ch03.asciidoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ch03.asciidoc b/ch03.asciidoc index efbdff5..49e025e 100644 --- a/ch03.asciidoc +++ b/ch03.asciidoc @@ -877,7 +877,7 @@ Using `Object.setPrototypeOf` to change the prototype of an object is an expensi [quote, Mozilla Developer Network] ____ -Changing the prototype of an object is, by the nature of how modern JavaScript engines optimize property accesses, a very slow operation, in every browser and JavaScript engine. The effects on performance of altering inheritance are subtle and far-flung, and are not limited to simply the time spent in a `obj.__proto__ = …` statement, but may extend to any code that has access to any object whose prototype has been altered. If you care about performance you should avoid setting the prototype of an object. Instead, create a new ((("objects", "built-in improvements", startref="ob3bii")))object with the desired ((("objects", "setting prototypes", startref="ob3sp")))((("Object.setPrototypeOf", startref="ospo3")))prototype using `Object.create()`. +Changing the prototype of an object is, by the nature of how modern JavaScript engines optimize property accesses, a very slow operation, in every browser and JavaScript engine. The effects on performance of altering inheritance are subtle and far-flung, and are not limited to simply the time spent in a `Object.setPrototypeOf(…)` statement, but may extend to any code that has access to any object whose prototype has been altered. If you care about performance you should avoid setting the prototype of an object. Instead, create a new ((("objects", "built-in improvements", startref="ob3bii")))object with the desired ((("objects", "setting prototypes", startref="ob3sp")))((("Object.setPrototypeOf", startref="ospo3")))prototype using `Object.create()`. ____ **** From 371a52b3e4662210b006e5f08be2c750c1d970a3 Mon Sep 17 00:00:00 2001 From: Vse Mozhet Byt Date: Mon, 18 Jun 2018 17:22:32 +0300 Subject: [PATCH 16/23] ch03: fix possible typo in "Local Symbols" section (#60) --- ch03.asciidoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ch03.asciidoc b/ch03.asciidoc index 49e025e..81d8ee4 100644 --- a/ch03.asciidoc +++ b/ch03.asciidoc @@ -428,7 +428,7 @@ console.log(JSON.stringify(character)) // <- '{"name":"Penguin"}' ---- -That being said, symbols are by no means a safe mechanism to conceal properties. Even though you won't stumble upon symbol properties when using reflection or serialization methods, symbols are revealed by a dedicated method as shown in the next snippet of code. In other words, symbols are not nonenumerable, but hidden in plain sight. Using `Object.getOwnPropertySymbols` we can retrieve all symbols used as property keys on any given object. +That being said, symbols are by no means a safe mechanism to conceal properties. Even though you won't stumble upon symbol properties when using pre-ES6 reflection, iteration or serialization methods, symbols are revealed by a dedicated method as shown in the next snippet of code. In other words, symbols are not nonenumerable, but hidden in plain sight. Using `Object.getOwnPropertySymbols` we can retrieve all symbols used as property keys on any given object. [source,javascript] ---- From 6670c7206d9e67a44f6199d8805b93256ac86577 Mon Sep 17 00:00:00 2001 From: Vse Mozhet Byt Date: Fri, 31 Aug 2018 20:52:52 +0300 Subject: [PATCH 17/23] ch4: fix typo in "Tree Traversal Using Generators" (#66) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit "when we can’t we move" -> "when we can’t move" --- ch04.asciidoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ch04.asciidoc b/ch04.asciidoc index 2bf7279..37dce19 100644 --- a/ch04.asciidoc +++ b/ch04.asciidoc @@ -1376,7 +1376,7 @@ class Node { } ---- -Trees can be traversed using depth-first search, where we always try to go deeper into the tree structure, and when we can't we move to the next children on the list. In the following tree structure, a depth-first search algorithm would traverse the tree visiting the nodes following the `1, 2, 3, 4, 5, 6, 7, 8, 9, 10` order. +Trees can be traversed using depth-first search, where we always try to go deeper into the tree structure, and when we can't move to the next children on the list. In the following tree structure, a depth-first search algorithm would traverse the tree visiting the nodes following the `1, 2, 3, 4, 5, 6, 7, 8, 9, 10` order. [source,javascript] ---- From 6b0b231c0ab2e747437f09f6f419a7c204d27148 Mon Sep 17 00:00:00 2001 From: Andrei Dobrinski Date: Mon, 15 Oct 2018 21:28:00 -0400 Subject: [PATCH 18/23] add space after period (#68) --- ch01.asciidoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ch01.asciidoc b/ch01.asciidoc index dfc7646..fac8b29 100644 --- a/ch01.asciidoc +++ b/ch01.asciidoc @@ -53,7 +53,7 @@ Firefox, Chrome, Edge, Safari, and Node.js all offer over 95% compliance of the The new process involves four different maturity stages.pass:[Take a look at the TC39 proposal process documentation.] The more mature a proposal is, the more likely it is to eventually make it into the specification. -Any ((("ES6 maturity stages")))((("proposal stages")))discussion, idea, or proposal for a change or addition that has not yet been submitted as a formal proposal is considered to be an aspirational "strawman" proposal (stage 0), but only ((("TC39 standards committee", startref="tc391")))TC39 members can create strawman proposals. At the time of this writing, there are over a dozen active strawman proposals.pass:[You can track strawman proposals.] +Any ((("ES6 maturity stages")))((("proposal stages")))discussion, idea, or proposal for a change or addition that has not yet been submitted as a formal proposal is considered to be an aspirational "strawman" proposal (stage 0), but only ((("TC39 standards committee", startref="tc391")))TC39 members can create strawman proposals. At the time of this writing, there are over a dozen active strawman proposals.pass:[ You can track strawman proposals.] At stage 1 a proposal is formalized and expected to address cross-cutting concerns, interactions with other proposals, and implementation concerns. Proposals at this stage should identify a discrete problem and offer a concrete solution to the problem. A stage 1 proposal often includes a high-level API description, illustrative usage examples, and a discussion of internal semantics and algorithms. Stage 1 proposals are likely to change significantly as they make their way through the process. From 13e0158b47788d9c329ca346dd24fc43eb4394c9 Mon Sep 17 00:00:00 2001 From: Andrei Dobrinski Date: Tue, 16 Oct 2018 12:08:35 -0400 Subject: [PATCH 19/23] update sentence syntax (#69) * update sentence syntax * fix breaking link --- ch03.asciidoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ch03.asciidoc b/ch03.asciidoc index 81d8ee4..ea97fea 100644 --- a/ch03.asciidoc +++ b/ch03.asciidoc @@ -884,7 +884,7 @@ ____ === Decorators -Decorators are, ((("Decorators", id="dec3")))as most things programming, definitely not a new concept. The pattern is fairly commonplace in modern programming languages: you have _attributes_ in C#, they're called _annotations_ in Java, there are _decorators_ in Python, and the list goes on. There's a JavaScript decorators proposalpass:[You can find the proposal draft online at GitHub.] in the works. It is currently sitting at stage 2 of the TC39 process. +Decorators are, ((("Decorators", id="dec3")))as most things programming, definitely not a new concept. The pattern is fairly commonplace in modern programming languages: you have _attributes_ in C#, they're called _annotations_ in Java, there are _decorators_ in Python, and the list goes on. There's a JavaScript decorators proposalpass:[ in the works and you can find the draft online at GitHub.] It is currently sitting at stage 2 of the TC39 process. ==== A Primer on JavaScript Decorators From 2b234a686f3b2bd200355f46ab5c05c7539cf9ff Mon Sep 17 00:00:00 2001 From: vladimirze Date: Wed, 13 Mar 2019 16:22:27 +0200 Subject: [PATCH 20/23] Fix typo `System.iterator` -> `Symbol.iterator` (#71) --- ch04.asciidoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ch04.asciidoc b/ch04.asciidoc index 37dce19..e2cbf59 100644 --- a/ch04.asciidoc +++ b/ch04.asciidoc @@ -1169,7 +1169,7 @@ console.log([...salute('you')]) // <- ['h', 'e', 'l', 'l', 'o', ' ', 'y', 'o', 'u'] ---- -To reiterate, you can `yield*` anything that adheres to the iterable protocol, not merely strings. That includes generator objects, arrays, `arguments`, `NodeList` in the browser, and just about anything, provided it implements `System.iterator`. The following example demonstrates how you could mix `yield` and `yield*` statements to describe a sequence of values using generator functions, an iterable object, and the spread operator. Can you deduce what the `console.log` statement would print? +To reiterate, you can `yield*` anything that adheres to the iterable protocol, not merely strings. That includes generator objects, arrays, `arguments`, `NodeList` in the browser, and just about anything, provided it implements `Symbol.iterator`. The following example demonstrates how you could mix `yield` and `yield*` statements to describe a sequence of values using generator functions, an iterable object, and the spread operator. Can you deduce what the `console.log` statement would print? [source,javascript] ---- From b1a162299807b5136201e7b34cd4d4fe7245560d Mon Sep 17 00:00:00 2001 From: Alexander Chaschin Date: Wed, 13 Mar 2019 17:22:51 +0300 Subject: [PATCH 21/23] Fix 'Scheme validation with proxies' part: (#70) * proper access to Map property through 'get' * dont return validation function result, just pass validation* --- ch06.asciidoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ch06.asciidoc b/ch06.asciidoc index 93f1603..f77ba57 100644 --- a/ch06.asciidoc +++ b/ch06.asciidoc @@ -205,7 +205,7 @@ const validations = new Map() const validator = { set(target, key, value) { if (validations.has(key)) { - return validations[key](value) + validations.get(key)(value) } return Reflect.set(target, key, value) } From 7f9241cf248c286f5589e82a58765ed1dbb21a9b Mon Sep 17 00:00:00 2001 From: James Bush Date: Mon, 24 Jun 2019 11:58:19 -0400 Subject: [PATCH 22/23] Fixes arrow function arguments description (#75) * Fixes description of arrow function arguments * Update ch02.asciidoc Co-Authored-By: Jordan Harband --- ch02.asciidoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ch02.asciidoc b/ch02.asciidoc index 575f16c..604de25 100644 --- a/ch02.asciidoc +++ b/ch02.asciidoc @@ -286,7 +286,7 @@ function puzzle() { puzzle('a', 'b', 'c')(1, 2, 3) ---- -In this case, the `arguments` object refers to the context of the `puzzle` function, because arrow functions don't create a closure. For this reason, the printed arguments will be `'a', 'b', 'c'`. +Because arrow functions don't have their own `arguments` keyword (or `this` or `super`), the lookup bubbles up to the outer scope of the `puzzle` function. That means the printed arguments will be `'a', 'b', 'c'`. I've mentioned there are several flavors of arrow functions, but so far we've only looked at their fully fleshed version. What are the other ways to represent an ((("arrow functions", "lexical scoping", startref="af2ls")))((("lexical scoping", startref="ls2")))arrow function? From 0275704d6e4cc29216f0bedb88ced92dfbf34a8a Mon Sep 17 00:00:00 2001 From: vladimirze Date: Wed, 14 Oct 2020 20:55:46 +0300 Subject: [PATCH 23/23] ch08: Fix footnote (#72) --- ch08.asciidoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ch08.asciidoc b/ch08.asciidoc index b0fc93f..28aa5cc 100644 --- a/ch08.asciidoc +++ b/ch08.asciidoc @@ -520,7 +520,7 @@ console.log(counter.default) // <- 2 ==== Dynamic import() -At the ((("dynamic import()", id="di8")))((("ES6 modules", "dynamic import()", id="esm8di")))time of this writing, a proposal for dynamic ++import()++pass:[Check out the proposal specification draft.] expressions is sitting at stage 3 of the TC39 proposal review process. Unlike `import` statements, which are statically analyzed and linked, `import()` loads modules at runtime, returning a promise for the module namespace object after fetching, parsing, and executing the requested module and all of its dependencies. +At the ((("dynamic import()", id="di8")))((("ES6 modules", "dynamic import()", id="esm8di")))time of this writing, a proposal for dynamic ++import()++pass:[Check out the proposal specification draft.] expressions is sitting at stage 3 of the TC39 proposal review process. Unlike `import` statements, which are statically analyzed and linked, `import()` loads modules at runtime, returning a promise for the module namespace object after fetching, parsing, and executing the requested module and all of its dependencies. The module specifier can be any string, like with `import` statements. Keep in mind `import` statements only allow statically defined plain string literals as module specifiers. In contrast, we're able to use template literals or any valid JavaScript expression to produce the module specifier string for `import()` function calls.