@@ -17,7 +17,7 @@ programmers feel good to imagine them as little things that just
1717happen to crawl into our work. In reality, of course, we put them
1818there ourselves.
1919
20- A program is crystallized thought. You can roughly categorize bugs
20+ If a program is crystallized thought, you can roughly categorize bugs
2121into those caused by the thoughts being confused, and those caused by
2222mistakes introduced while converting a thought to code. The former
2323type is generally harder to diagnose and fix than the latter.
@@ -31,8 +31,8 @@ computer, if it knew enough about what we're trying to do. But here
3131JavaScript's looseness is a hindrance. Its concept of bindings and
3232properties is vague enough that it will rarely catch ((typo))s before
3333actually running the program. And even then, it allows you to do some
34- clearly nonsensical things without complaint, such as `true *
35- "monkey"`.
34+ clearly nonsensical things without complaint, such as computing
35+ ` true * "monkey"` .
3636
3737{{index syntax}}
3838
@@ -41,7 +41,7 @@ program that does not follow the language's ((grammar)) will
4141immediately make the computer complain. Other things, such as calling
4242something that's not a function or looking up a ((property)) on an
4343((undefined)) value, will cause an error to be reported when the
44- program is running and encounters the action.
44+ program tries to perform the action.
4545
4646{{index NaN, error}}
4747
@@ -85,8 +85,8 @@ with `counter` in the example, JavaScript quietly creates a global
8585binding and uses that. In strict mode an ((error)) is reported
8686instead. This is very helpful. It should be noted, though, that this
8787doesn't work when the binding in question already exists as a global
88- binding, in which case the loop will still quietly overwrite the value
89- of that binding.
88+ binding. In that case the loop will still quietly overwrite the value
89+ of the binding.
9090
9191{{index this, "global object", undefined, "strict mode"}}
9292
@@ -134,11 +134,11 @@ a problem even in non-strict mode.
134134Strict mode does a few more things. It disallows giving a function
135135multiple parameters with the same name and removes certain problematic
136136language features entirely (such as the ` with ` statement, which is so
137- problematic it is not further discussed in this book).
137+ wrong it is not further discussed in this book).
138138
139139{{index debugging}}
140140
141- In short, putting a ` "use strict" ` at the top of your program rarely
141+ In short, putting ` "use strict" ` at the top of your program rarely
142142hurts and might help you spot a problem.
143143
144144## Types
@@ -168,12 +168,13 @@ function goalOrientedRobot(state, memory) {
168168There are a number of different conventions for annotating JavaScript
169169programs with types.
170170
171- What do you think would be the type of the ` randomPick ` function that
172- returns a random element from an array? One thing about types is that
173- they require their own complexity to describe some code. In this case,
174- you'd need a _ ((type variable))_ _ T_ , which can stand in for any type,
175- at which point you can give ` randomPick ` a type like ` ([T]) → T `
176- (function from array of * T* s to a * T* ).
171+ One thing about types is that they need to introduce their own
172+ complexity to be able to describe enough code to be useful. What do
173+ you think would be the type of the ` randomPick ` function that returns
174+ a random element from an array? You'd need to introduce a _ ((type
175+ variable))_ , _ T_ , which can stand in for any type, so that you can
176+ give ` randomPick ` a type like ` ([T]) → T ` (function from an array of
177+ * T* s to a * T* ).
177178
178179{{index "type checking", TypeScript}}
179180
@@ -198,9 +199,8 @@ we'll have to find them the hard way: by running the program and
198199seeing whether it does the right thing.
199200
200201Doing this by hand, again and again, is a really bad idea. Not only is
201- it annoying, it will also necessarily be ineffective, since it takes
202- too much time to exhaustively test everything every time you make a
203- change.
202+ it annoying, it also tends to be ineffective, since it takes too much
203+ time to exhaustively test everything every time you make a change.
204204
205205Computers are good at repetitive tasks, and testing is the ideal
206206repetitive task. Automated testing is the process of writing a program
@@ -223,10 +223,10 @@ function test(label, body) {
223223 if (!body()) console.log(`Failed: ${label}`);
224224}
225225
226- test("convert Latin text to upper case ", () => {
226+ test("convert Latin text to uppercase ", () => {
227227 return "hello".toUpperCase() == "HELLO";
228228});
229- test("convert Greek text to upper case ", () => {
229+ test("convert Greek text to uppercase ", () => {
230230 return "Χαίρετε".toUpperCase() == "ΧΑΊΡΕΤΕ";
231231});
232232test("don't convert case-less characters", () => {
@@ -246,11 +246,10 @@ These are usually called _((test runners))_.
246246{{index "persistent data structure"}}
247247
248248Some code is easier to test than other code. Generally, the more
249- external objects that it interacts with, the harder it is to set up
250- the context in which to test it. The style of programming shown in the
251- [ previous chapter] ( robot ) , which uses self-contained persistent values
252- rather than changing objects, tends to produce code that's easy to
253- test.
249+ external objects that the code interacts with, the harder it is to set
250+ up the context in which to test it. The style of programming shown in
251+ the [ previous chapter] ( robot ) , which uses self-contained persistent
252+ values rather than changing objects, tends be easy to test.
254253
255254## Debugging
256255
@@ -268,10 +267,9 @@ description and that line of code, you can often see the problem.
268267
269268But not always. Sometimes the line that triggered the problem is
270269simply the first place where a flaky value produced elsewhere gets
271- used in an invalid way. And sometimes there is no error message at
272- all—just an invalid result. If you have been solving the ((exercises))
273- in the earlier chapters, you will probably have already experienced
274- such situations.
270+ used in an invalid way. If you have been solving the ((exercises)) in
271+ earlier chapters, you will probably have already experienced such
272+ situations.
275273
276274{{index "decimal number", "binary number"}}
277275
@@ -357,8 +355,8 @@ whenever it reaches such a statement.
357355
358356Not all problems can be prevented by the programmer, unfortunately. If
359357your program communicates with the outside world in any way, it is
360- possible to get malformed input, or to have the network fail , or to
361- become overloaded with work .
358+ possible to get malformed input, to become overloaded with work , or to
359+ have the network fail .
362360
363361{{index "error recovery"}}
364362
@@ -368,7 +366,7 @@ going to be used by anybody else, you usually want the program to do
368366better than just crashing. Sometimes the right thing to do is take the
369367bad input in stride and continue running. In other cases, it is better
370368to report to the user what went wrong and then give up. But in either
371- situation, the program has to actively take action in response to the
369+ situation, the program has to actively do something in response to the
372370problem.
373371
374372{{index "promptInteger function", validation}}
@@ -423,8 +421,8 @@ function lastElement(array) {
423421The second issue with returning special values is that it can lead to
424422very awkward code. If a piece of code calls ` promptNumber ` 10 times,
425423it has to check 10 times whether ` null ` was returned. And if its
426- response to finding ` null ` is to simply return ` null ` itself, the
427- caller will in turn have to check for it, and so on.
424+ response to finding ` null ` is to simply return ` null ` itself, callers
425+ of the function will in turn have to check for it, and so on.
428426
429427## Exceptions
430428
@@ -436,7 +434,7 @@ how to handle the problem. This is what _((exception handling))_ does.
436434
437435{{index "control flow", "raising (exception)", "throw keyword", "call stack"}}
438436
439- Exceptions are a mechanism that make it possible for code that runs
437+ Exceptions are a mechanism that makes it possible for code that runs
440438into a problem to _ raise_ (or _ throw_ ) an exception. An exception can
441439be any value. Raising one somewhat resembles a super-charged return
442440from a function: it jumps out of not just the current function but
@@ -467,10 +465,11 @@ function promptDirection(question) {
467465}
468466
469467function look() {
470- if (promptDirection("Which way?") == "L")
468+ if (promptDirection("Which way?") == "L") {
471469 return "a house";
472- else
470+ } else {
473471 return "two angry bears";
472+ }
474473}
475474
476475try {
@@ -504,7 +503,7 @@ the failing call.
504503
505504{{index "exception handling"}}
506505
507- Note that the function ` look ` completely ignores the possibility that
506+ Note that the ` look ` function completely ignores the possibility that
508507` promptDirection ` might go wrong. This is the big advantage of
509508exceptions—error-handling code is necessary only at the point where
510509the error occurs and at the point where it is handled. The functions
@@ -517,9 +516,9 @@ Well, almost...
517516{{index "exception handling", "cleaning up"}}
518517
519518The effect of an exception is another kind of ((control flow)). Every
520- action that might cause an exception, which is at least every function
521- call and property access, might cause control to suddenly leave your
522- code.
519+ action that might cause an exception, which is pretty much every
520+ function call and property access, might cause control to suddenly
521+ leave your code.
523522
524523That means that when code has several side effects, even if its
525524"regular" control flow looks like they'll always all happen, an
@@ -530,7 +529,7 @@ exception might prevent some of them from taking place.
530529Here is some really bad banking code.
531530
532531``` {includeCode: true}
533- let accounts = {
532+ const accounts = {
534533 a: 100,
535534 b: 0,
536535 c: 20
@@ -577,9 +576,8 @@ there is no problem.
577576But that isn't always practical. So there is another feature that
578577` try ` statements have. They may be followed by a ` finally ` block
579578either instead of or in addition to a ` catch ` block. A ` finally ` block
580- means "No matter _ what_ happens, run this code after trying to run the
581- code in the ` try ` block". If a function has to clean something up, the
582- cleanup code should usually be put into a ` finally ` block.
579+ says "no matter _ what_ happens, run this code after trying to run the
580+ code in the ` try ` block".
583581
584582``` {includeCode: true}
585583function transfer(from, amount) {
@@ -639,7 +637,7 @@ were on the stack when the problem occurred.
639637{{index "user interface"}}
640638
641639For problems that are _ expected_ to happen during routine use,
642- crashing with an unhandled exception is not a very friendly response .
640+ crashing with an unhandled exception is a terrible strategy .
643641
644642{{index syntax, [ function, application] , "exception handling", "Error type"}}
645643
@@ -701,14 +699,14 @@ carefully about how you might be hiding information.
701699
702700So we want to catch a _ specific_ kind of exception. We can do this by
703701checking in the ` catch ` block whether the exception we got is the one
704- we are interested in and by rethrowing it otherwise. But how do we
702+ we are interested in and rethrowing it otherwise. But how do we
705703recognize an exception?
706704
707- Of course, we could compare its ` message ` property against the
708- ((error)) message we happen to expect. But that's a shaky way to write
709- code—we'd be using information that's intended for human consumption
710- (the message) to make a programmatic decision. As soon as someone
711- changes (or translates) the message, the code will stop working.
705+ We could compare its ` message ` property against the ((error)) message
706+ we happen to expect. But that's a shaky way to write code—we'd be
707+ using information that's intended for human consumption (the message)
708+ to make a programmatic decision. As soon as someone changes (or
709+ translates) the message, the code will stop working.
712710
713711{{index "Error type", "instanceof operator", "promptDirection function"}}
714712
@@ -790,7 +788,7 @@ for such mistakes to go unnoticed, and easier to find their cause when
790788they occur.
791789
792790I do not recommend trying to write assertions for every possible kind
793- of bad input. That'd be a lot of work, and would lead to very noisy
791+ of bad input. That'd be a lot of work and would lead to very noisy
794792code. You'll want to reserve them for mistakes that are easy to make
795793(or that you find yourself making).
796794
@@ -804,15 +802,15 @@ assertions to your programs.
804802Problems caused by factors outside the program's control should
805803usually be handled gracefully. Sometimes, when the problem can be
806804handled locally, special return values are a good way to track them.
807- Otherwise, exceptions are preferable.
805+ Otherwise, exceptions may be preferable.
808806
809807Throwing an exception causes the call stack to be unwound until the
810808next enclosing ` try/catch ` block or until the bottom of the stack. The
811809exception value will be given to the ` catch ` block that catches it,
812810which should verify that it is actually the expected kind of exception
813811and then do something with it. To help address the unpredictable
814812control flow caused by exceptions, ` finally ` blocks can be used to
815- ensure a piece of code is _ always_ run when a block finishes.
813+ ensure a piece of code _ always_ runs when a block finishes.
816814
817815## Exercises
818816
@@ -836,10 +834,11 @@ Make sure you handle only the exceptions you are trying to handle.
836834class MultiplicatorUnitFailure extends Error {}
837835
838836function primitiveMultiply(a, b) {
839- if (Math.random() < 0.2)
837+ if (Math.random() < 0.2) {
840838 return a * b;
841- else
839+ } else {
842840 throw new MultiplicatorUnitFailure("Klunk");
841+ }
843842}
844843
845844function reliableMultiply(a, b) {
@@ -874,8 +873,8 @@ hint}}
874873
875874Consider the following (rather contrived) object:
876875
877- ``` {includeCode: true}
878- let box = {
876+ ```
877+ const box = {
879878 locked: true,
880879 unlock() { this.locked = false; },
881880 lock() { this.locked = true; },
@@ -889,9 +888,9 @@ let box = {
889888
890889{{index "private property", "access control"}}
891890
892- It is a ((box)) with a lock. Inside is an array, but you can get at it
893- only when the box is unlocked. Directly accessing the private
894- ` _content ` property is forbidden.
891+ It is a ((box)) with a lock. There is an array in the box , but you can
892+ get at it only when the box is unlocked. Directly accessing the
893+ private ` _content ` property is forbidden.
895894
896895{{index "finally keyword", "exception handling"}}
897896
@@ -903,6 +902,17 @@ argument function returned normally or threw an exception.
903902{{if interactive
904903
905904```
905+ const box = {
906+ locked: true,
907+ unlock() { this.locked = false; },
908+ lock() { this.locked = true; },
909+ _content: [],
910+ get content() {
911+ if (this.locked) throw new Error("Locked!");
912+ return this._content;
913+ }
914+ };
915+
906916function withBoxUnlocked(body) {
907917 // Your code here.
908918}
@@ -931,10 +941,9 @@ if}}
931941
932942{{index "locked box (exercise)", "finally keyword", "try keyword"}}
933943
934- This exercise calls for a ` finally ` block, as you may have guessed.
935- Your function should first unlock the box and then call the argument
936- function from inside a ` try ` body. The ` finally ` block after it should
937- lock the box again.
944+ This exercise calls for a ` finally ` block. Your function should first
945+ unlock the box and then call the argument function from inside a ` try `
946+ body. The ` finally ` block after it should lock the box again.
938947
939948To make sure we don't lock the box when it wasn't already locked,
940949check its lock at the start of the function and unlock and lock
0 commit comments