You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: ch01.asciidoc
+7-7Lines changed: 7 additions & 7 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -6,7 +6,7 @@ JavaScript has gone from being a 1995 marketing ploy to gain a tactical advantag
6
6
7
7
How did JavaScript get here, and where is it going next?
8
8
9
-
=== 1.1 A Brief History of JavaScript Standards
9
+
=== A Brief History of JavaScript Standards
10
10
11
11
Back in 1995, Netscape envisioned a dynamic web beyond what HTML could offer. Brendan Eich was initially brought into Netscape to develop a language that was functionally akin to Scheme, but for the browser. Once he joined, he learned that upper management wanted it to look like Java and a deal to that effect was already underway.
12
12
@@ -43,7 +43,7 @@ In parallel with the ES6 effort, in 2012 the WHATWG (a standards body interested
43
43
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.
44
44
45
45
[[ecmascript_as_a_rolling_standard]]
46
-
=== 1.2 ECMAScript as a Rolling Standard
46
+
=== ECMAScript as a Rolling Standard
47
47
48
48
Having spent ten years without observing significant change to the language specification after ES3, and four years for ES6 to materialize, it was clear the TC39 process needed to improve. The revision process used to be deadline-driven. Any delay in arriving at consensus would cause long wait periods between revisions, which lead to feature creep, causing more delays. Minor revisions were delayed by large additions to the specification, and large additions faced pressure to finalize so that the revision would be pushed through avoiding further delays.
49
49
@@ -67,7 +67,7 @@ New releases of the specification are expected to be published every year from n
67
67
68
68
The streamlined proposal process combined with the yearly cut into standardization translates into a more consistent publication process, and it also means specification revision numbers are becoming less important. The focus is now on proposal stagesfootnoteref:[tc39-proposals], and we can expect references to specific revisions of the ECMAScript standard to become more uncommon.
69
69
70
-
=== 1.3 Browser Support and Complementary Tooling
70
+
=== Browser Support and Complementary Tooling
71
71
72
72
A stage 3 candidate recommendation proposal is most likely to make it into the specification in the next cut, provided two independent implementations land in JavaScript engines. Effectively, stage 3 proposals are considered safe to use in real-world applications, be it through an experimental engine implementation, a polyfill, or using a compiler. Stage 2 and earlier proposals are also used in the wild by JavaScript developers, tightening the feedback loop between implementors and consumers.
73
73
@@ -81,7 +81,7 @@ The same applies to ES7 and beyond. As new versions of the language specificatio
81
81
82
82
Let's talk about how you can use Babel in as part of your workflow.
83
83
84
-
==== 1.3.1 Introduction to the Babel transpiler
84
+
==== Introduction to the Babel transpiler
85
85
86
86
Babel can compile modern JavaScript code using 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.
87
87
@@ -216,7 +216,7 @@ console.log(double(3))
216
216
217
217
Let's jump into a different kind of tool, the `eslint` code linter, which can help us establish a code quality baseline for our applications.
218
218
219
-
==== 1.3.2 Code Quality and Consistency with ESLint
219
+
==== Code Quality and Consistency with ESLint
220
220
221
221
As we develop a codebase we factor out snippets that are redundant or no longer useful, write new pieces of code, delete features that are no longer relevant or necessary, and shift chunks of code around while accomodating a new architecture. As the codebase grows, the team working on it changes as well: at first it may be a handful of people or even one person, but as the project grows in size so might the team.
222
222
@@ -318,7 +318,7 @@ A similar kind of tool can be found in `prettier`, which can be used to automati
318
318
319
319
Now that you know how to compile modern JavaScript into something every browser understands, and how to properly lint and format your code, let's jump into ES6 feature themes and the future of JavaScript.
320
320
321
-
=== 1.4 Feature Themes in ES6
321
+
=== Feature Themes in ES6
322
322
323
323
ES6 is big: the language specification went from 258 pages in ES5.1 to over double that amount in ES6, at 566 pages. Each change to the specification falls in some of a few different categories:
324
324
@@ -342,7 +342,7 @@ We are getting a new module system that's native to JavaScript. After going over
342
342
343
343
Due to the sheer amount of changes introduced by ES6, it's hard to reconcile its new features with our pre-existing knowledge of JavaScript. We'll spend all of <<practical-considerations>> analyzing the merits and importance of different individual features in ES6, so that you have a practical grounding upon which you can start experimenting with ES6 right away.
344
344
345
-
=== 1.5 Future of JavaScript
345
+
=== Future of JavaScript
346
346
347
347
The JavaScript language has evolved from its humble beginnings in 1995, to the formidable language it is today. While ES6 is a great step forward, it's not the finish line. Given we can expect new specification updates every year, it's important to learn how to stay up to date with the specification.
Copy file name to clipboardExpand all lines: ch02.asciidoc
+26-26Lines changed: 26 additions & 26 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -5,7 +5,7 @@ The sixth edition of the language comes with a plethora of non-breaking syntax i
5
5
6
6
Object literals get a few syntax changes in ES6, and they're a good place to start.
7
7
8
-
=== 2.1 Object Literals
8
+
=== Object Literals
9
9
10
10
An object literal is any object declaration using the `{}` shorthand syntax, such as the following example.
11
11
@@ -20,7 +20,7 @@ var book = {
20
20
21
21
ES6 brings a few improvements to object literal syntax: property value shorthands, computed property names, and method definitions. Let's go through them and describe their use cases as well.
22
22
23
-
==== 2.1.1 Property Value Shorthands
23
+
==== Property Value Shorthands
24
24
25
25
Sometimes we declare objects with one or more properties whose values are references to variables by the same name. For example we might have a `listeners` collection, and in order to assign it to a property called `listeners` of an object literal, we have to repeat its name. The following snippet has a typical example where we have an object literal declaration with a couple of these repetitive properties.
26
26
@@ -62,7 +62,7 @@ function clear() {
62
62
63
63
That's the first of many ES6 features that are aimed towards reducing complexity in the code you have to maintain. Once you get used to the syntax, you'll notice that code readability and developer productivity get boosts as well.
64
64
65
-
==== 2.1.2 Computed Property Names
65
+
==== Computed Property Names
66
66
67
67
Sometimes you have to declare objects that contain properties with names based on variables or other JavaScript expressions, as shown in the following piece of code written in ES5. For this example, assume that `expertise` is provided to you as a function parameter, and is not a value you know beforehand.
68
68
@@ -153,7 +153,7 @@ function getEnvelope(type, description) {
153
153
154
154
The last enhancement coming to object literals is about functions.
155
155
156
-
==== 2.1.3 Method Definitions
156
+
==== Method Definitions
157
157
158
158
Typically, you can declare methods on an object by adding properties to it. In the next snippet we're creating an small event emitter which supports multiple kinds of events. It comes with an `emitter#on` method that can be used to register event listeners, and an `emitter#emit` method that can be used to raise events.
159
159
@@ -204,7 +204,7 @@ var emitter = {
204
204
Arrow functions are another way of declaring functions in ES6, and they come in several flavors. Let's investigate what arrow functions are, how they can be declared, and how they behave semantically.
205
205
206
206
[[arrow_functions]]
207
-
=== 2.2 Arrow Functions
207
+
=== Arrow Functions
208
208
209
209
In JavaScript you typically declare functions using code like the following, where you have a name, a list of parameters, and a function body.
210
210
@@ -237,7 +237,7 @@ While arrow functions look very similar to your typical anonymous function, they
237
237
238
238
Let's dig into their semantic differences with traditional functions, the many ways to declare an arrow function, and practical use cases.
239
239
240
-
==== 2.2.1 Lexical Scoping
240
+
==== Lexical Scoping
241
241
242
242
In the body of an arrow function, `this`, `arguments` and `super` point to the containing scope, since arrow functions don't create a new scope. Consider the following example. We have a `timer` object with a `seconds` counter and a `start` method defined using the syntax we've learned about earlier. We then start the timer, wait for a few seconds, and log the current amount of elapsed `seconds`.
243
243
@@ -290,7 +290,7 @@ In this case, the `arguments` object refers to the context of the `puzzle` funct
290
290
291
291
I've mentioned there's several flavors of arrow functions, but so far we've only looked at their fully fleshed version. What are the others way to represent an arrow function?
292
292
293
-
==== 2.2.2 Arrow Function Flavors
293
+
==== Arrow Function Flavors
294
294
295
295
Let's look one more time at the arrow function syntax we've learned so far.
296
296
@@ -364,7 +364,7 @@ Wrapping the expression in parenthesis fixes these issues, because the compiler
364
364
365
365
Now that you understand arrow functions, let's ponder about their merits and where they might be a good fit.
366
366
367
-
==== 2.2.3 Merits and Use Cases
367
+
==== Merits and Use Cases
368
368
369
369
As a rule of thumb, you shouldn't blindly adopt ES6 features wherever you can. Instead, it's best to reason about each case individually and see whether adopting the new feature actually improves code readibility and maintainability. ES6 features are not strictly better than what we had all along, and it's a bad idea to treat them as such.
370
370
@@ -395,11 +395,11 @@ Arrow functions are neat when it comes to defining anonymous functions that shou
395
395
// <- 8
396
396
----
397
397
398
-
=== 2.3 Assignment Destructuring
398
+
=== Assignment Destructuring
399
399
400
400
This is one of the most flexible and expressive features in ES6. It's also one of the simplest. It binds properties to as many variables as you need. It works with objects, arrays, and even in `function` parameter lists. Let's go step by step, starting with objects.
401
401
402
-
==== 2.3.1 Destructuring Objects
402
+
==== Destructuring Objects
403
403
404
404
Imagine 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.
405
405
@@ -544,7 +544,7 @@ This flavor of destructuring is probably the least useful, as `characterBoots =
544
544
545
545
That's it, as far as objects go, in terms of destructuring. What about arrays?
546
546
547
-
==== 2.3.2 Destructuring Arrays
547
+
==== Destructuring Arrays
548
548
549
549
The syntax for destructuring arrays is similar to that of objects. The following example shows a `coordinates` object that's destructured into two variables: `x` and `y`. Note how the notation uses square brackets instead of curly braces, this denotes we're using array destructuring instead of object destructuring. Instead of having to sprinkle your code with implementation details like `x = coordinates[0]`, with destructuring you can convey your meaning clearly and without explicitly referencing the indices, naming the values instead.
550
550
@@ -598,7 +598,7 @@ var right = 7
598
598
599
599
The last area of destructuring we'll be covering is function parameters.
600
600
601
-
==== 2.3.3 Function Parameter Defaults
601
+
==== Function Parameter Defaults
602
602
603
603
Function parameters in ES6 enjoy the ability of specifying default values as well. The following example defines a default `exponent` with the most commonly used value.
604
604
@@ -651,7 +651,7 @@ carFactory({ make: 2000 })
651
651
652
652
We can mix function parameter default values with destructuring, and get the best of both worlds.
653
653
654
-
==== 2.3.4 Function Parameter Destructuring
654
+
==== Function Parameter Destructuring
655
655
656
656
A better approach than merely providing a default value might be to destructure `options` entirely, providing default values for each property, individually, within the destructuring pattern. This approach also lets you reference each option without going through an `options` object, but you lose the ability to reference `options` directly, which might represent an issue in some situations.
657
657
@@ -716,7 +716,7 @@ getCarProductModel(car)
716
716
717
717
Besides default values and filling an `options` object, let's explore what else destructuring is good at.
718
718
719
-
==== 2.3.5 Use Cases for Destructuring
719
+
==== Use Cases for Destructuring
720
720
721
721
Whenever there's a function that returns an object or an array, destructuring makes it much terser to interact with. The following example shows a function that returns an object with some coordinates, where we grab only the ones we're interested in: `x` and `y`. We're avoiding an intermediate `point` variable declaration that often gets in the way without adding a lot of value to the readability of your code.
Let's turn our attention to spread and rest operators next.
767
767
768
-
=== 2.4 Rest Parameters and Spread Operator
768
+
=== Rest Parameters and Spread Operator
769
769
770
770
Before ES6, interacting with an arbitrary amount of function parameters was complicated. You had to use `arguments`, which isn't an array but has a `length` property. Usually you'd end up casting the `arguments` object into an actual array using `Array#slice.call`, and going from there, as shown in the following snippet.
ES6 has a better solution to the problem, and that's rest parameters.
783
783
784
-
==== 2.4.1 Rest Parameters
784
+
==== Rest Parameters
785
785
786
786
You can now precede the last parameter in any JavaScript function with three dots, converting it into an special "rest parameter". When the rest parameter is the only parameter in a function, it gets all arguments passed to the function: it works just like the `.slice` solution we saw earlier, but you avoid the need for a complicated construct like `arguments`, and it's specified in the parameter list.
787
787
@@ -830,7 +830,7 @@ console.log(sumAll(1, 2, 5))
830
830
831
831
Next up we have the spread operator. It's also denoted with three dots, but it serves a slightly different purpose.
832
832
833
-
==== 2.4.2 Spread Operator
833
+
==== Spread Operator
834
834
835
835
The spread operator can be used to cast any iterable object into an array. Spreading effectively expands an expression onto a target such as an array literal or a function call. The following example uses `...arguments` to cast function parameters into an array literal.
836
836
@@ -956,7 +956,7 @@ The following table summarizes the use cases we've discussed for the spread oper
956
956
|=======
957
957
958
958
[[template_literals]]
959
-
=== 2.5 Template Literals
959
+
=== Template Literals
960
960
961
961
Template literals are a vast improvement upon regular JavaScript strings. Instead of using single or double quotes, template literals are declared using backticks, as shown next.
962
962
@@ -974,7 +974,7 @@ var text = `I'm "amazed" at these opportunities!`
974
974
975
975
One of the most appealing features of template literals is their ability to interpolate JavaScript expressions.
976
976
977
-
==== 2.5.1 String Interpolation
977
+
==== String Interpolation
978
978
979
979
With template literals, you're able to interpolate any JavaScript expressions inside your templates. When the template literal expression is reached, it's evaluated and you get back the compiled result. The following example interpolates a `name` variable into a template literal.
980
980
@@ -1014,7 +1014,7 @@ You could even nest template literals, as they are also valid JavaScript express
1014
1014
1015
1015
Another perk of template literals is their multiline string representation support.
1016
1016
1017
-
==== 2.5.2 Multiline Template Literals
1017
+
==== Multiline Template Literals
1018
1018
1019
1019
Before template literals, if you wanted to represent strings in multiple lines of JavaScript, you had to resort to escaping, concatenation, arrays, or even ellaborate hacks using comments. The following snippet summarizes some of the most common ways multiline string representations prior to ES6.
1020
1020
@@ -1124,7 +1124,7 @@ function unindent(text) {
1124
1124
1125
1125
Sometimes, it might be a good idea to pre-process the results of interpolated expressions before inserting them into your templates. For these advanced kinds of use cases, it's possible to use another feature of template literals called tagged templates.
1126
1126
1127
-
==== 2.5.3 Tagged Templates
1127
+
==== Tagged Templates
1128
1128
1129
1129
By default, JavaScript interprets `\` as an escape character with special meaning. For example, `\n` is interpreted as a newline, `\u00f1` is interpreted as `ñ`, etcetera. You could avoid these rules using the `String.raw` tagged template. The next snippet shows a template literal using `String.raw` which prevents `\n` from being interpreted as a newline.
1130
1130
@@ -1210,7 +1210,7 @@ console.log(html)
1210
1210
1211
1211
Phew, that malicious `<iframe>` almost got us. Rounding out ES6 syntax changes, we have the `let` and `const` statements.
1212
1212
1213
-
=== 2.6 Let and Const Statements
1213
+
=== Let and Const Statements
1214
1214
1215
1215
The `let` statement is one of the most well-known features in ES6. It works like a `var` statement, but it has different scoping rules.
1216
1216
@@ -1245,7 +1245,7 @@ function isItTwo(value) {
1245
1245
1246
1246
Whether we like it or not, hoisting is more confusing than having block-scoped variables would be. Block scoping works on the curly braces level, rather than the function level.
1247
1247
1248
-
==== 2.6.1 Block Scoping and Let Statements
1248
+
==== Block Scoping and Let Statements
1249
1249
1250
1250
Instead of having to declare a new `function` if we want a deeper scoping level, block scoping allows you to just leverage existing code branches like those in `if`, `for`, or `while` statements; you could also create new `{}` blocks arbitrarily. As you may or may not know, the JavaScript language allows us to create an indiscriminate number of blocks, just because we want to.
1251
1251
@@ -1324,7 +1324,7 @@ printNumbers()
1324
1324
1325
1325
One more thing of note about `let` is a concept called the "Temporal Dead Zone".
1326
1326
1327
-
==== 2.6.2 Temporal Dead Zone
1327
+
==== Temporal Dead Zone
1328
1328
1329
1329
In so many words: if you have code such as the following code snippet, it'll throw. Once execution enters a scope, and until a `let` statement is reached, attempting to access the variable for said `let` statement will throw. This is known as the Temporal Dead Zone (TDZ).
1330
1330
@@ -1391,7 +1391,7 @@ The whole point of the TDZ is to make it easier to catch errors where accessing
1391
1391
1392
1392
We made it through the temporal dead zone! It's now time to cover `const`, a similar statement to `let` but with a few major differences.
1393
1393
1394
-
==== 2.6.3 Const Statements
1394
+
==== Const Statements
1395
1395
1396
1396
The `const` statement is block scoped like `let`, and it follows TDZ semantics as well. In fact, TDZ semantics were implemented because of `const`, and then TDZ was also applied to `let` for consistency. The reason why `const` needed TDZ semantics is that it would otherwise have been possible to assign a value to a hoisted `const` variable before reaching the `const` declaration, meaning that the declaration itself would throw. The temporal dead zone defines a solution that solves the problem of making `const` assignment possible only at declaration time, helps avoid potential issues when using `let`, and also makes it easy to eventually implement other features that benefit from TDZ semantics.
1397
1397
@@ -1467,7 +1467,7 @@ frozen.push('Water')
1467
1467
1468
1468
Let's take a moment to discuss the merits of `const` and `let`.
1469
1469
1470
-
==== 2.6.4 Merits of Const and Let
1470
+
==== Merits of Const and Let
1471
1471
1472
1472
New features should never be used for the sake of using new features. ES6 features should be used where they genuinely improve code readability and maintainability. The `let` statement is able to, in many cases, simplify pieces of code where you'd otherwise declare `var` statements at the top of a function just so that hoisting doesn't produce unexpected results. Using the `let` statement you'd be able to place your declarations at the top of a code block, instead of the top of the whole function, reducing the latency in mental trips to the top of the scope.
0 commit comments