Skip to content

Commit 352d78f

Browse files
committed
Merge pull request nzakas#295 from nzakas/appedits
App A edits
2 parents 63a08b4 + 2cfda45 commit 352d78f

File tree

2 files changed

+75
-72
lines changed

2 files changed

+75
-72
lines changed

manuscript/A-Other-Changes.md

Lines changed: 53 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
1-
# Appendix A: Other Changes
1+
# Appendix A: Smaller Changes
22

3-
Along with the changes already mentioned in the book, ECMAScript 6 has made some very small changes and improvements. This appendix lists out those changes.
3+
Along with the major changes this book has already covered, ECMAScript 6 made several other changes that are smaller but still helpful in improving JavaScript. Those changes include making integers easier to use, adding new methods for calculations, a tweak to Unicode identifiers, and formalizing the`__proto__` property. I describe all of those in this appendix.
44

55
## Working with Integers
66

7-
A lot of confusion has been related to JavaScript's single number encoding, IEEE 754, that is used to represent both integers and floats. The language goes through great pains to ensure that developers don't need to worry about the details, but problems still leak through from time to time. ECMAScript 6 seeks to address this by making it easier to identify and work with integers.
7+
JavaScript uses the IEEE 754 encoding system to represent both integers and floats, which has caused a lot of confusion over the years. The language takes great pains to ensure that developers don't need to worry about the details of number encoding, but problems still leak through from time to time. ECMAScript 6 seeks to address this by making integers easier to identify and work with.
88

99
### Identifying Integers
1010

11-
The first addition is `Number.isInteger()`, which allows you to determine if a value represents an integer in JavaScript. Since integers and floats are stored differently, the JavaScript engine looks at the underlying representation of the value to make this determination. That means numbers that look like floats might actually be stored as integers and therefore return `true` from `Number.isInteger()`. For example:
11+
First, ECMAScript 6 added the `Number.isInteger()` method, which can determine whether a value represents an integer in JavaScript. While JavaScript uses IEEE 754 to represent both types of numbers, floats and integers are stored differently. The `Number.isInteger()` method takes advantage of that, and when the method is called on a value, the JavaScript engine looks at the underlying representation of the value to determine whether that value is an integer. That means numbers that look like floats might actually be stored as integers and cause `Number.isInteger()` to return `true`. For example:
1212

1313
```js
1414
console.log(Number.isInteger(25)); // true
@@ -20,16 +20,16 @@ In this code, `Number.isInteger()` returns `true` for both `25` and `25.0` even
2020

2121
### Safe Integers
2222

23-
IEEE 754 can only accurately represent integers between -2^53^ and 2^53^, and outside of this "safe" range, binary representations end up reused for multiple numeric values. That means JavaScript can only safely represent integers within the IEEE 754 range before problems become apparent. For example:
23+
IEEE 754 can only accurately represent integers between -2^53^ and 2^53^, and outside this "safe" range, binary representations end up reused for multiple numeric values. That means JavaScript can only safely represent integers within the IEEE 754 range before problems become apparent. For instance, consider this code:
2424

2525
```js
2626
console.log(Math.pow(2, 53)); // 9007199254740992
2727
console.log(Math.pow(2, 53) + 1); // 9007199254740992
2828
```
2929

30-
This example doesn't contain a typo, two different numbers end up represented by the same JavaScript integer. The effect becomes more prevalent the further the value is outside of the safe range.
30+
This example doesn't contain a typo, yet two different numbers are represented by the same JavaScript integer. The effect becomes more prevalent the further the value falls outside the safe range.
3131

32-
ECMAScript 6 introduces `Number.isSafeInteger()` to better identify integers that can accurately be represented in the language, and also adds `Number.MAX_SAFE_INTEGER` and `Number.MIN_SAFE_INTEGER` that represent the upper and lower bounds of the same range, respectively. The `Number.isSafeInteger()` method ensures that a value is an integer and falls within the safe range of integer values:
32+
ECMAScript 6 introduced the `Number.isSafeInteger()` method to better identify integers that the language can accurately represent. It also added the `Number.MAX_SAFE_INTEGER` and `Number.MIN_SAFE_INTEGER` properties to represent the upper and lower bounds of the integer range, respectively. The `Number.isSafeInteger()` method ensures that a value is an integer and falls within the safe range of integer values, as in this example:
3333

3434
```js
3535
var inside = Number.MAX_SAFE_INTEGER,
@@ -42,79 +42,84 @@ console.log(Number.isInteger(outside)); // true
4242
console.log(Number.isSafeInteger(outside)); // false
4343
```
4444

45-
The number `inside` is the largest safe integer, so it returns `true` for both `Number.isInteger()` and `Number.isSafeInteger()`. The number `outside` is the first questionable integer value, so it is no longer considered safe even though it's still an integer.
45+
The number `inside` is the largest safe integer, so it returns `true` for both the `Number.isInteger()` and `Number.isSafeInteger()` methods. The number `outside` is the first questionable integer value, and it isn't considered safe even though it's still an integer.
4646

47-
Most of the time, you only want to deal with safe integers when doing integer arithmetic or comparisons in JavaScript, so it's a good idea to use `Number.isSafeInteger()` as part of input validation.
47+
Most of the time, you only want to deal with safe integers when doing integer arithmetic or comparisons in JavaScript, so using `Number.isSafeInteger()` as part of input validation is a good idea.
4848

4949
## New Math Methods
5050

51-
The new emphasis on gaming and graphics that led to the inclusion of typed arrays in JavaScript also led to the realization that many mathematical calculations could be done more efficiently by a JavaScript engine. Optimization strategies like asm.js, which works on a subset of JavaScript to improve performance, need more information to perform calculations in the fastest way possible. It's important, for instance, to know whether the numbers should be treated as 32-bit integers or as 64-bit floats so hardware-based operations can be used (which are much faster than software-based operations).
52-
53-
As a result, ECMAScript 6 adds several new methods to the `Math` object. These new methods are important for improving the speed of common mathematical calculations, and therefore, improving the speed of applications that must perform many calculations (such as graphics programs). The new methods are listed below.
54-
55-
| Method | Description |
56-
|--------|-------------|
57-
|`Math.acosh(x)`| Returns the inverse hyperbolic cosine of `x`. |
58-
|`Math.asinh(x)`| Returns the inverse hyperbolic sine of `x`. |
59-
|`Math.atanh(x)`| Returns the inverse hyperbolic tangent of `x` |
60-
|`Math.cbrt(x)`| Returns the cubed root of `x`. |
61-
|`Math.clz32(x)`| Returns the number of leading zero bits in the 32-bit integer representation of `x`. |
62-
|`Math.cosh(x)`| Returns the hyperbolic cosine of `x`. |
63-
|`Math.expm1(x)`| Returns the result of subtracting 1 from the exponential function of `x`|
64-
|`Math.fround(x)`| Returns the nearest single-precision float of `x`.|
65-
|`Math.hypot(...values)`| Returns the square root of the sum of the squares of each argument. |
66-
|`Math.imul(x, y)`| Returns the result of performing true 32-bit multiplication of the two arguments. |
67-
|`Math.log1p(x)`| Returns the natural logarithm of `1 + x`. |
68-
|`Math.log10(x)`| Returns the base 10 logarithm of `x`. |
69-
|`Math.log2(x)`| Returns the base 2 logarithm of `x`. |
70-
|`Math.sign(x)`| Returns -1 if the `x` is negative, 0 if `x` is +0 or -0, or 1 if `x` is positive.|
71-
|`Math.sinh(x)`| Returns the hyperbolic sine of `x`. |
72-
|`Math.tanh(x)`| Returns the hyperbolic tangent of `x`. |
73-
|`Math.trunc(x)`| Removes fraction digits from a float and returns an integer.|
74-
75-
It's beyond the scope of this book to explain each new method and what it does in detail. However, if you are looking for a reasonably common calculation, be sure to check the new `Math` methods before implementing it yourself.
51+
The new emphasis on gaming and graphics that led ECMAScript 6 to include typed arrays in JavaScript also led to the realization that a JavaScript engine could do many mathematical calculations more efficiently. But optimization strategies like asm.js, which works on a subset of JavaScript to improve performance, need more information to perform calculations in the fastest way possible. For instance, knowing whether the numbers should be treated as 32-bit integers or as 64-bit floats is important for hardware-based operations, which are much faster than software-based operations.
52+
53+
As a result, ECMAScript 6 added several methods to the `Math` object to improve the speed of common mathematical calculations. Improving the speed of common calculations also improves the overall speed of applications that perform many calculations, such as graphics programs. The new methods are listed below:
54+
55+
* `Math.acosh(x)` Returns the inverse hyperbolic cosine of `x`.
56+
* `Math.asinh(x)` Returns the inverse hyperbolic sine of `x`.
57+
* `Math.atanh(x)` Returns the inverse hyperbolic tangent of `x`
58+
* `Math.cbrt(x)` Returns the cubed root of `x`.
59+
* `Math.clz32(x)` Returns the number of leading zero bits in the 32-bit integer representation of `x`.
60+
* `Math.cosh(x)` Returns the hyperbolic cosine of `x`.
61+
* `Math.expm1(x)` Returns the result of subtracting 1 from the exponential function of `x`
62+
* `Math.fround(x)` Returns the nearest single-precision float of `x`.
63+
* `Math.hypot(...values)` Returns the square root of the sum of the squares of each argument.
64+
* `Math.imul(x, y)` Returns the result of performing true 32-bit multiplication of the two arguments.
65+
* `Math.log1p(x)` Returns the natural logarithm of `1 + x`.
66+
* `Math.log10(x)` Returns the base 10 logarithm of `x`.
67+
* `Math.log2(x)` Returns the base 2 logarithm of `x`.
68+
* `Math.sign(x)` Returns -1 if the `x` is negative, 0 if `x` is +0 or -0, or 1 if `x` is positive.
69+
* `Math.sinh(x)` Returns the hyperbolic sine of `x`.
70+
* `Math.tanh(x)` Returns the hyperbolic tangent of `x`.
71+
* `Math.trunc(x)` Removes fraction digits from a float and returns an integer.
72+
73+
It's beyond the scope of this book to explain each new method and what it does in detail. But if your application needs to a reasonably common calculation, be sure to check the new `Math` methods before implementing it yourself.
7674

7775
## Unicode Identifiers
7876

79-
Better Unicode support in ECMAScript 6 also means changes to what characters may be used for an identifier. In ECMAScript 5, it was already possible to use Unicode escape sequences for identifiers, such as:
77+
ECMAScript 6 offers better Unicode support than previous versions of JavaScript, and it also changes what characters may be used as identifiers. In ECMAScript 5, it was already possible to use Unicode escape sequences for identifiers. For example:
8078

8179
```js
8280
// Valid in ECMAScript 5 and 6
8381
var \u0061 = "abc";
8482

85-
console.log(\u0061); // "abc"
83+
console.log(\u0061); // "abc"
8684

87-
// equivalent to
88-
// console.log(a); // "abc"
85+
// equivalent to:
86+
console.log(a); // "abc"
8987
```
9088

91-
In ECMAScript 6, you can also use Unicode code point escape sequences as identifiers:
89+
After the `var` statement in this example, you can use either `\u0061` or `a` to access the variable. In ECMAScript 6, you can also use Unicode code point escape sequences as identifiers, like this:
9290

9391
```js
9492
// Valid in ECMAScript 5 and 6
9593
var \u{61} = "abc";
9694

97-
console.log(\u{61}); // "abc"
95+
console.log(\u{61}); // "abc"
9896

99-
// equivalent to
100-
// console.log(a); // "abc"
97+
// equivalent to:
98+
console.log(a); // "abc"
10199
```
102100

103-
Additionally, ECMAScript 6 formally specifies valid identifiers in terms of [Unicode Standard Annex #31: Unicode Identifier and Pattern Syntax](http://unicode.org/reports/tr31/):
101+
This example just replaces `\u0061` with its code point equivalent. Otherwise, it does exactly the same thing as the previous example.
102+
103+
Additionally, ECMAScript 6 formally specifies valid identifiers in terms of [Unicode Standard Annex #31: Unicode Identifier and Pattern Syntax](http://unicode.org/reports/tr31/), which gives the following rules:
104104

105105
1. The first character must be `$`, `_`, or any Unicode symbol with a derived core property of `ID_Start`.
106-
1. Each subsequent character must be `$`, `_`, `\u200c` (zero-width non-joiner), `\u200d` (zero-width joiner), or any Unicode symbol with a derived core property of `ID_Continue`.
106+
1. Each subsequent character must be `$`, `_`, `\u200c` (a zero-width non-joiner), `\u200d` (a zero-width joiner), or any Unicode symbol with a derived core property of `ID_Continue`.
107107

108-
The `ID_Start` and `ID_Continue` derived core properties are defined in Unicode Identifier and Pattern Syntax as a way to identify symbols that are appropriate for use in identifiers such as variables and domain names (the specification is not specific to JavaScript).
108+
The `ID_Start` and `ID_Continue` derived core properties are defined in Unicode Identifier and Pattern Syntax as a way to identify symbols that are appropriate for use in identifiers such as variables and domain names. The specification is not specific to JavaScript.
109109

110110
## Formalizing the `__proto__` Property
111111

112-
Even before ECMAScript 5 was finished, several JavaScript engines already implemented a custom property called `__proto__` that could be used to both get and set `[[Prototype]]`. Effectively, `__proto__` was an early precursor to both the `Object.getPrototypeOf()` and `Object.setPrototypeOf()` methods. It was unrealistic to expect all JavaScript engines to remove this property, so ECMAScript 6 also formalized the `__proto__` behavior. However, the formalization is in Appendix B along with this warning:
112+
Even before ECMAScript 5 was finished, several JavaScript engines already implemented a custom property called `__proto__` that could be used to both get and set the `[[Prototype]]` property. Effectively, `__proto__` was an early precursor to both the `Object.getPrototypeOf()` and `Object.setPrototypeOf()` methods. Expecting all JavaScript engines to remove this property is unrealistic, so ECMAScript 6 also formalized the `__proto__` behavior. But the formalization appears in Appendix B of ECMA-262 along with this warning:
113113

114114
> These features are not considered part of the core ECMAScript language. Programmers should not use or assume the existence of these features and behaviours when writing new ECMAScript code. ECMAScript implementations are discouraged from implementing these features unless the
115115
implementation is part of a web browser or is required to run the same legacy ECMAScript code that web browsers encounter.
116116

117-
While it's best to avoid using `__proto__`, it's interesting to see how the specification defined it. In ECMAScript 6 engines, `Object.prototype.__proto__` is defined as an accessor property whose `get` method calls `Object.getPrototypeOf()` and whose `set` method calls the `Object.setPrototypeOf()` method. This leaves no real difference between using `__proto__` and the other methods, except that `__proto__` allows you to set the prototype of an object literal directly. Here's how that works:
117+
The ECMAScript specification recommends using `Object.getPrototypeOf()` and `Object.setPrototypeOf()` instead because `__proto__` has the following characteristics:
118+
119+
1. You can only specify `__proto__` once in an object literal. If you specify two `__proto__` properties, then an error is thrown. This is the only object literal property with that restriction.
120+
1. The computed form `["__proto__"]` acts like a regular property and doesn't set or return the current object's prototype. All rules related to object literal properties apply in this form, as opposed to the non-computed form, which has exceptions.
121+
122+
While you should avoid using the `__proto__` property, the way the specification defined it is interesting. In ECMAScript 6 engines, `Object.prototype.__proto__` is defined as an accessor property whose `get` method calls `Object.getPrototypeOf()` and whose `set` method calls the `Object.setPrototypeOf()` method. This leaves no real difference between using `__proto__` and `Object.getPrototypeOf()`/`Object.setPrototypeOf()`, except that `__proto__` allows you to set the prototype of an object literal directly. Here's how that works:
118123

119124
```js
120125
let person = {
@@ -144,11 +149,4 @@ console.log(friend.__proto__ === dog); // true
144149
console.log(Object.getPrototypeOf(friend) === dog); // true
145150
```
146151

147-
This example is functionally equivalent to the `getGreeting()` example. The call to `Object.create()` is replaced with an object literal that assigns a value to the `__proto__` property. The only real difference between creating an object with `Object.create()` or an object literal with `__proto__` is that the former requires you to specify full property descriptors for any additional object properties. The latter is just a standard object literal.
148-
149-
W> The `__proto__` property is special in a number of ways:
150-
W>
151-
W> 1. You can only specify it once in an object literal. If you specify two `__proto__` properties, then an error is thrown. This is the only object literal property with that restriction.
152-
W> 1. The computed form `["__proto__"]` acts like a regular property and doesn't set or return the current object's prototype. All rules related to object literal properties apply in this form, as opposed to the non-computed form, which has exceptions.
153-
W>
154-
W> For these reasons, it's recommend to avoid using `__proto__` when you can use `Object.getPrototypeOf()` and `Object.setPrototypeOf()` instead.
152+
Instead of calling `Object.create()` to make the `friend` object, this example creates a standard object literal that assigns a value to the `__proto__` property. When creating an object with the `Object.create()` method, on the other hand, you'd have to specify full property descriptors for any additional object properties.

0 commit comments

Comments
 (0)