Skip to content

Commit 2ee2abc

Browse files
authored
Follow review by @kentcdodds (mjavascript#25)
* Following @kentcdodds' review of Chapter 3 * Use more backticks * Follow kent's next video * Finished reviewing most of @kentcdodds' arguments * defineGetter as code
1 parent b0200ab commit 2ee2abc

File tree

9 files changed

+164
-160
lines changed

9 files changed

+164
-160
lines changed

chapters/ch01.asciidoc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ A couple of years later, in June 2011, the specification was once again reviewed
3737

3838
It took TC39 another four years to formalize ECMAScript 6, in June 2015. The sixth edition is the largest update to the language that made its way into publication, implementing many of the ES4 proposals that were deferred as part of the Harmony resolution. Throughout this book, we'll be exploring ES6 in depth.
3939

40-
In parallel with the ES6 effort, in 2012 the WHATWG (a standards body interested in pushing the web forward) set out to document the differences between ES5.1 and browser implementations, in terms of compatibility and interoperability requirements. The taskforce standardized +String#substr+, which was previously unspecified; unified several methods for wrapping strings in HTML tags, which were inconsistent across browsers; and documented +Object.prototype+ properties like +__proto__+ and +__defineGetter__+, among other improvementsfootnote:[For the full set of changes made when merging the Web ECMAScript specification upstream, see: https://mjavascript.com/out/javascript-standard.]. This effort was condensed into a separate Web ECMAScript specification, which eventually made its way into Annex B in 2015. Annex B was an informative section of the core ECMAScript specification, meaning implementations weren't required to follow its suggestions. Jointly with this update, Annex B was also made normative and required for web browsers.
40+
In parallel with the ES6 effort, in 2012 the WHATWG (a standards body interested in pushing the web forward) set out to document the differences between ES5.1 and browser implementations, in terms of compatibility and interoperability requirements. The taskforce standardized +String#substr+, which was previously unspecified; unified several methods for wrapping strings in HTML tags, which were inconsistent across browsers; and documented +Object.prototype+ properties like `__proto__` and `__defineGetter__`, among other improvementsfootnote:[For the full set of changes made when merging the Web ECMAScript specification upstream, see: https://mjavascript.com/out/javascript-standard.]. This effort was condensed into a separate Web ECMAScript specification, which eventually made its way into Annex B in 2015. Annex B was an informative section of the core ECMAScript specification, meaning implementations weren't required to follow its suggestions. Jointly with this update, Annex B was also made normative and required for web browsers.
4141

4242
The sixth edition is a significant milestone in the history of JavaScript. Besides the dozens of new features, ES6 marks a key inflection point where ECMAScript would become a rolling standard.
4343

chapters/ch02.asciidoc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1137,7 +1137,7 @@ console.log(html)
11371137
// <- '<div>A malicious comment</div>'
11381138
----
11391139

1140-
Phew, that malicious +<iframe>+ almost got us. Rounding out ES6 syntax changes, we have the +let+ and +const statements.
1140+
Phew, that malicious +<iframe>+ almost got us. Rounding out ES6 syntax changes, we have the +let+ and +const+ statements.
11411141

11421142
=== 2.6 Let and Const Statements
11431143

chapters/ch03.asciidoc

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[[classes-symbols-and-symbols]]
22
== Classes, Symbols, and Objects
33

4-
Now that we've covered the basic improvements to the syntax, we're in good shape to take aim at a few other additions to the language: classes, and symbols. Classes provide syntax to represent prototypal inheritance under the traditional class-based programming paradigm. Symbols are a new primitive value type in JavaScript useful for defining protocols, and we'll investigate what that means. When we're done with classes and symbols, we'll discuss a few new static methods added to the +Object+ built-in in ES6.
4+
Now that we've covered the basic improvements to the syntax, we're in good shape to take aim at a few other additions to the language: classes, and symbols. Classes provide syntax to represent prototypal inheritance under the traditional class-based programming paradigm. Symbols are a new primitive value type in JavaScript, like strings, booleans, and numbers. They can be used for defining protocols, and in this chapter we'll investigate what that means. When we're done with classes and symbols, we'll discuss a few new static methods added to the +Object+ built-in in ES6.
55

66
=== 3.1 Classes
77

@@ -81,7 +81,7 @@ class Fruit {
8181
}
8282
----
8383

84-
A not-so-minor detail you might have missed is that there aren't any commas in between method declarations of the +Fruit+ class. That's not a mistake our copious copy editors missed, but rather part of the +class+ syntax. The distinction can help avoid mistakes where we treat plain objects and classes as interchangeable even though they're not, and at the same time it makes classes better suited for future improvements to the syntax such as class-scoped private functions.
84+
A not-so-minor detail you might have missed is that there aren't any commas in between method declarations of the +Fruit+ class. That's not a mistake our copious copy editors missed, but rather part of the +class+ syntax. The distinction can help avoid mistakes where we treat plain objects and classes as interchangeable even though they're not, and at the same time it makes classes better suited for future improvements to the syntax such as public and private class fields.
8585

8686
The class-based solution is equivalent to the prototype-based piece of code we wrote earlier. Consuming a fruit wouldn't change in the slightest, the API for +Fruit+ remains unchanged. The previous piece of code where we instantiated an apple, chopped it into smaller pieces and ate most of it would work well with our +class+ flavored +Fruit+ as well.
8787

@@ -94,7 +94,7 @@ class Person {
9494
}
9595
----
9696

97-
Besides the class declaration syntax presented above, classes can also be declared as expressions, just like with function declarations and function expressions. You are allowed to omit the name for a +class+ expression, as shown in the following bit of code.
97+
Besides the class declaration syntax presented above, classes can also be declared as expressions, just like with function declarations and function expressions. You may omit the name for a +class+ expression, as shown in the following bit of code.
9898

9999
[source,javascript]
100100
----
@@ -105,7 +105,7 @@ const Person = class {
105105
}
106106
----
107107

108-
Class expressions could be easily returned from a function, making it possible to create a factory of classes with minimal effort. In the following example we create a +Jake+ class dynamically in arrow function which takes a name parameter and then feeds that to the parent +Person+ constructor via +super()+.
108+
Class expressions could be easily returned from a function, making it possible to create a factory of classes with minimal effort. In the following example we create a +JakePerson+ class dynamically in arrow function which takes a name parameter and then feeds that to the parent +Person+ constructor via +super()+.
109109

110110
[source,javascript]
111111
----
@@ -114,8 +114,8 @@ const createPersonClass = name => class extends Person {
114114
super(name)
115115
}
116116
}
117-
const Jake = createPersonClass('Jake')
118-
const jake = new Jake()
117+
const JakePerson = createPersonClass('Jake')
118+
const jake = new JakePerson()
119119
----
120120

121121
We'll dig deeper into class inheritance later. Let's take a more nuanced look at properties and methods first.
@@ -128,7 +128,7 @@ It should be noted that the +constructor+ method declaration is an optional memb
128128
----
129129
class Fruit {
130130
}
131-
// the constructor function below is equivalent to the class above
131+
// the constructor function below is roughly equivalent to the class above
132132
function Fruit () {
133133
}
134134
----
@@ -360,12 +360,12 @@ Like numbers or strings, symbols are immutable. Unlike other value types, howeve
360360

361361
[source,javascript]
362362
----
363+
console.log(Number(3) === Number(3))
364+
// <- true
363365
console.log(Symbol() === Symbol())
364366
// <- false
365367
console.log(Symbol('my symbol') === Symbol('my symbol'))
366368
// <- false
367-
console.log(Number(3) === Number(3))
368-
// <- true
369369
----
370370

371371
Symbols are of type +symbol+, new in ES6. The following snippet shows how +typeof+ returns the new type string for symbols.
@@ -512,7 +512,7 @@ Besides local symbols, there's also a global symbol registry, accessible from ac
512512

513513
==== 3.2.3 Global Symbol Registry
514514

515-
A code realm is any JavaScript execution context, such as the page your application is running in, an +<iframe>+ within that page, an script running through +eval+, or a worker of any kind -- such as web workers, service workers, or shared workers. Each of these execution contexts has its own global object. Global variables defined on the +window+ object of a page, for example, aren't available to a +ServiceWorker+. In contrast, the global symbol registry is shared across all code realms.
515+
A code realm is any JavaScript execution context, such as the page your application is running in, an +<iframe>+ within that page, a script running through +eval+, or a worker of any kind -- such as web workers, service workers, or shared workersfootnote:[Workers are a way of executing background tasks in browsers. The initiator can communicate with their workers, which run in a different execution context, via messaging. https://mjavascript.com/out/workers]. Each of these execution contexts has its own global object. Global variables defined on the +window+ object of a page, for example, aren't available to a +ServiceWorker+. In contrast, the global symbol registry is shared across all code realms.
516516

517517
There's two methods that interact with the runtime-wide global symbol registry: +Symbol.for+ and +Symbol.keyFor+. What do they do?
518518

@@ -529,7 +529,7 @@ console.log(example === Symbol.for('example'))
529529
// <- true
530530
----
531531

532-
That contrasts with what we knew about symbols being unique. The global symbol registry keeps track of symbols by their +key+. Note that the +key+ will also be used as a +description+ when the symbols that go into the registry are created. Considering these symbols are global on a runtime-wide level, you might want to prefix symbol keys in the global registry with a value that identifies your library or component, mitigating potential name clashes.
532+
The global symbol registry keeps track of symbols by their +key+. Note that the +key+ will also be used as a +description+ when the symbols that go into the registry are created. Considering these symbols are global on a runtime-wide level, you might want to prefix symbol keys in the global registry with a value that identifies your library or component, mitigating potential name clashes.
533533

534534
===== Using +Symbol.keyFor(symbol)+ to retrieve symbol keys
535535

@@ -576,13 +576,13 @@ console.log(s1 === s2)
576576
// <- true
577577
----
578578

579-
There's tradeoffs in using widely available symbols. On the one hand, they make it easy for libraries to expose their own symbols, but on the other hand they could also expose their symbols on their own API, using local symbols. The symbol registry is obviously useful when symbols need to be shared across any two code realms, for example: +ServiceWorker+ and a web page. The API is also convenient when you don't want to bother storing references to the symbols, you could use the registry directly for that, since every call with a given +key+ is guaranteed to return the same +symbol+. You'll have to keep in mind, though, that these symbols are shared across the runtime and that might lead to unwanted consequences if you use generic symbol names like +each+ or +contains+.
579+
There are tradeoffs in using widely available symbols. On the one hand, they make it easy for libraries to expose their own symbols, but on the other hand they could also expose their symbols on their own API, using local symbols. The symbol registry is obviously useful when symbols need to be shared across any two code realms, for example: +ServiceWorker+ and a web page. The API is also convenient when you don't want to bother storing references to the symbols, you could use the registry directly for that, since every call with a given +key+ is guaranteed to return the same +symbol+. You'll have to keep in mind, though, that these symbols are shared across the runtime and that might lead to unwanted consequences if you use generic symbol names like +each+ or +contains+.
580580

581-
There's one more kind of symbols, the built-in well-known symbols.
581+
There's one more kind of symbols: built-in well-known symbols.
582582

583583
==== 3.2.4 Well-known Symbols
584584

585-
So far we've covered symbols you can create using the +Symbol+ function and those you can create through +Symbol.for+. The third and last kind of symbols we're going to cover is the well-known symbols. These are built into the language instead of created by the user, and they provide hooks into internal language behavior allowing you to extend or customize aspects of the language that weren't accessible prior to ES6.
585+
So far we've covered symbols you can create using the +Symbol+ function and those you can create through +Symbol.for+. The third and last kind of symbols we're going to cover is the well-known symbols. These are built into the language instead of created by JavaScript developers, and they provide hooks into internal language behavior allowing you to extend or customize aspects of the language that weren't accessible prior to ES6.
586586

587587
A great example of how symbols can add extensibility to the language without breaking existing code is the +Symbol.toPrimitive+ well-known symbol. It can be assigned a function to determine how an object is casted into a primitive value. The function receives a +hint+ parameter that can be +'string'+, +'number'+, or +'default'+, indicating what type of primitive value is expected.
588588

@@ -796,7 +796,7 @@ These differences may not seem like much, but dealing with +NaN+ has always been
796796

797797
==== 3.3.3 +Object.setPrototypeOf+
798798

799-
The +Object.setPrototypeOf+ method does exactly what its name conveys: it sets the prototype of an object to a reference to another object. It's considered the proper way of setting the prototype, as opposed to using +__proto__+ which is a legacy feature.
799+
The +Object.setPrototypeOf+ method does exactly what its name conveys: it sets the prototype of an object to a reference to another object. It's considered the proper way of setting the prototype, as opposed to using `__proto__` which is a legacy feature.
800800

801801
Before ES6, we were introduced to +Object.create+ in ES5. Using that method, we could create an object based on any prototype passed into +Object.create+, as shown next.
802802

@@ -824,7 +824,7 @@ Using +Object.setPrototypeOf+ to change the prototype of an object is an expensi
824824
825825
[quote, Mozilla Developer Network]
826826
____
827-
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 object with the desired prototype using +Object.create()+.
827+
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 object with the desired prototype using +Object.create()+.
828828
____
829829
====
830830

0 commit comments

Comments
 (0)