提交 9190c480 编写于 作者: G gdut-yy

添加图片 ch9-ch13-ch15

上级 9b70410b
......@@ -306,8 +306,8 @@ Let’s bring this back to our URL-fetching example. When c1 returns p4, p2 is r
This can be one of the trickiest parts of JavaScript to understand, and you may need to read this section more than once. Figure 13-1 presents the process in visual form and may help clarify it for you.
js7e 1301
Figure 13-1. Fetching a URL with Promises
<Figures figure="13-1">Fetching a URL with Promises</Figures>
### 13.2.4 More on Promises and Errors
Earlier in the chapter, we saw that you can pass a second callback function to the .then() method and that this second function will be invoked if the Promise is rejected. When that happens, the argument to this second callback function is a value—typically an Error object—that represents the reason for the rejection. We also learned that it is uncommon (and even unidiomatic) to pass two callbacks to a .then() method. Instead, Promise-related errors are typically handled by adding a .catch() method invocation to a Promise chain. Now that we have examined Promise chains, we can return to error handling and discuss it in more detail. To preface the discussion, I’d like to stress that careful error handling is really important when doing asynchronous programming. With synchronous code, if you leave out error-handling code, you’ll at least get an exception and a stack trace that you can use to figure out what is going wrong. With asynchronous code, unhandled exceptions will often go unreported, and errors can occur silently, making them much harder to debug. The good news is that the .catch() method makes it easy to handle errors when working with Promises.
......
......@@ -150,8 +150,8 @@ The top-level `<html>` tag contains `<head>` and `<body>` tags. The `<head>` tag
The DOM API mirrors the tree structure of an HTML document. For each HTML tag in the document, there is a corresponding JavaScript Element object, and for each run of text in the document, there is a corresponding Text object. The Element and Text classes, as well as the Document class itself, are all subclasses of the more general Node class, and Node objects are organized into a tree structure that JavaScript can query and traverse using the DOM API. The DOM representation of this document is the tree pictured in Figure 15-1.
js7e 1501
Figure 15-1. The tree representation of an HTML document
<Figures figure="15-1">The tree representation of an HTML document</Figures>
If you are not already familiar with tree structures in computer programming, it is helpful to know that they borrow terminology from family trees. The node directly above a node is the parent of that node. The nodes one level directly below another node are the children of that node. Nodes at the same level, and with the same parent, are siblings. The set of nodes any number of levels below another node are the descendants of that node. And the parent, grandparent, and all other nodes above a node are the ancestors of that node.
The DOM API includes methods for creating new Element and Text nodes, and for inserting them into the document as children of other Element objects. There are also methods for moving elements within the document and for removing them entirely. While a server-side application might produce plain-text output by writing strings with console.log(), a client-side JavaScript application can produce formatted HTML output by building or manipulating the document tree document using the DOM API.
......@@ -796,9 +796,9 @@ The outerHTML property of an Element is like innerHTML except that its value inc
A related Element method is insertAdjacentHTML(), which allows you to insert a string of arbitrary HTML markup “adjacent” to the specified element. The markup is passed as the second argument to this method, and the precise meaning of “adjacent” depends on the value of the first argument. This first argument should be a string with one of the values “beforebegin,” “afterbegin,” “beforeend,” or “afterend.” These values correspond to insertion points that are illustrated in Figure 15-2.
js7e 1502
Figure 15-2. Insertion points for insertAdjacentHTML()
ELEMENT CONTENT AS PLAIN TEXT
<Figures figure="15-2">Insertion points for insertAdjacentHTML()</Figures>
#### ELEMENT CONTENT AS PLAIN TEXT
Sometimes you want to query the content of an element as plain text or to insert plain text into a document (without having to escape the angle brackets and ampersands used in HTML markup). The standard way to do this is with the textContent property:
```js
let para = document.querySelector("p"); // First <p> in the document
......@@ -1232,8 +1232,8 @@ scrollWidth and scrollHeight return the size of an element’s content area plus
## 15.6 Web Components
HTML is a language for document markup and defines a rich set of tags for that purpose. Over the last three decades, it has become a language that is used to describe the user interfaces of web applications, but basic HTML tags such as `<input>` and `<button>` are inadequate for modern UI designs. Web developers are able to make it work, but only by using CSS and JavaScript to augment the appearance and behavior of basic HTML tags. Consider a typical user interface component, such as the search box shown in Figure 15-3.
js7e 1503
Figure 15-3. A search box user interface component
<Figures figure="15-3">A search box user interface component</Figures>
The HTML `<input>` element can be used to accept a single line of input from the user, but it doesn’t have any way to display icons like the magnifying glass on the left and the cancel X on the right. In order to implement a modern user interface element like this for the web, we need to use at least four HTML elements: an `<input>` element to accept and display the user’s input, two `<img>` elements (or in this case, two `<span>` elements displaying Unicode glyphs), and a container `<div>` element to hold those three children. Furthermore, we have to use CSS to hide the default border of the `<input>` element and define a border for the container. And we need to use JavaScript to make all the HTML elements work together. When the user clicks on the X icon, we need an event handler to clear the input from the `<input>` element, for example.
That is a lot of work to do every time you want to display a search box in a web application, and most web applications today are not written using “raw” HTML. Instead, many web developers use frameworks like React and Angular that support the creation of reusable user interface components like the search box shown here. Web components is a browser-native alternative to those frameworks based on three relatively recent additions to web standards that allow JavaScript to extend HTML with new tags that work as self-contained, reusable UI components.
......@@ -1318,8 +1318,9 @@ As an example of a custom element, suppose we want to be able to display circles
How many marbles does the document contain now?
</p>
```
js7e 15in01
Figure 15-4. An inline circle custom element
<Figures figure="15-4">An inline circle custom element</Figures>
We can implement this `<inline-circle>` custom element with the code shown in Example 15-2:
Example 15-2. The `<inline-circle>` custom element
......@@ -1668,8 +1669,8 @@ One reason to embed SVG directly into your HTML files (instead of just using sta
It is also possible to dynamically manipulate SVG graphics that are directly embedded in HTML. The clock face example in the previous section displays a static clock with hour and minute hands facing straight up displaying the time noon or midnight. But you may have noticed that the HTML file includes a `<script>` tag. That script runs a function periodically to check the time and transform the hour and minute hands by rotating them the appropriate number of degrees so that the clock actually displays the current time, as shown in Figure 15-5.
js7e 1504
Figure 15-5. A scripted SVG analog clock
<Figures figure="15-5">A scripted SVG analog clock</Figures>
The code to manipulate the clock is straightforward. It determines the proper angle of the hour and minute hands based on the current time, then uses querySelector() to look up the SVG elements that display those hands, then sets a transform attribute on them to rotate them around the center of the clock face. The function uses setTimeout() to ensure that it runs once a minute:
```js
(function updateClock() { // Update the SVG clock graphic to show current time
......@@ -1697,8 +1698,8 @@ In addition to simply scripting SVG images embedded in your HTML documents, you
Even though SVG tags can be included within HTML documents, they are technically XML tags, not HTML tags, and if you want to create SVG elements with the JavaScript DOM API, you can’t use the normal createElement() function that was introduced in §15.3.5. Instead you must use createElementNS(), which takes an XML namespace string as its first argument. For SVG, that namespace is the literal string “http://www.w3.org/2000/svg.”
js7e 1505
Figure 15-6. An SVG pie chart built with JavaScript (data from Stack Overflow’s 2018 Developer Survey of Most Popular Technologies)
<Figures figure="15-6">An SVG pie chart built with JavaScript (data from Stack Overflow’s 2018 Developer Survey of Most Popular Technologies)</Figures>
Other than the use of createElementNS(), the pie chart–drawing code in Example 15-4 is relatively straightforward. There is a little math to convert the data being charted into pie-slice angles. The bulk of the example, however, is DOM code that creates SVG elements and sets attributes on those elements.
The most opaque part of this example is the code that draws the actual pie slices. The element used to display each slice is `<path>`. This SVG element describes arbitrary shapes comprised of lines and curves. The shape description is specified by the d attribute of the `<path>` element. The value of this attribute uses a compact grammar of letter codes and numbers that specify coordinates, angles, and other values. The letter M, for example, means “move to” and is followed by x and y coordinates. The letter L means “line to” and draws a line from the current point to the coordinates that follow it. This example also uses the letter A to draw an arc. This letter is followed by seven numbers describing the arc, and you can look up the syntax online if you want to know more.
......@@ -1875,8 +1876,8 @@ c.stroke(); // Stroke two sides of the triangle
```
This code (along with some additional code to set line widths and fill colors) produced the drawing shown in Figure 15-7.
js7e 1506
Figure 15-7. A simple path, filled and stroked
<Figures figure="15-7">A simple path, filled and stroked</Figures>
Notice that the subpath defined in Figure 15-7 is “open.” It consists of just two line segments, and the end point is not connected back to the starting point. This means that it does not enclose a region. The fill() method fills open subpaths by acting as if a straight line connected the last point in the subpath to the first point in the subpath. That is why this code fills a triangle, but strokes only two sides of the triangle.
If you wanted to stroke all three sides of the triangle just shown, you would call the closePath() method to connect the end point of the subpath to the start point. (You could also call lineTo(100,100), but then you end up with three line segments that share a start and end point but are not truly closed. When drawing with wide lines, the visual results are better if you use closePath().)
......@@ -1892,8 +1893,8 @@ The second point to note about stroke() and fill() is that neither one alters th
Example 15-5 defines a function for drawing regular polygons and demonstrates the use of moveTo(), lineTo(), and closePath() for defining subpaths and of fill() and stroke() for drawing those paths. It produces the drawing shown in Figure 15-8.
js7e 1507
Figure 15-8. Regular polygons
<Figures figure="15-8">Regular polygons</Figures>
Example 15-5. Regular polygons with moveTo(), lineTo(), and closePath()
```js
// Define a regular polygon with n sides, centered at (x,y) with radius r.
......@@ -1955,8 +1956,8 @@ The lineWidth property specifies how wide (in CSS pixels) the lines drawn by str
When drawing lines that are more than about two pixels wide, the lineCap and lineJoin properties can have a significant impact on the visual appearance of the ends of a path and the vertices at which two path segments meet. Figure 15-9 illustrates the values and resulting graphical appearance of lineCap and lineJoin.
js7e 1508
Figure 15-9. The lineCap and lineJoin attributes
<Figures figure="15-9">The lineCap and lineJoin attributes</Figures>
The default value for lineCap is “butt.” The default value for lineJoin is “miter.” Note, however, that if two lines meet at a very narrow angle, then the resulting miter can become quite long and visually distracting. If the miter at a given vertex would be longer than half of the line width times the miterLimit property, that vertex will be drawn with a beveled join instead of a mitered join. The default value for miterLimit is 10.
The stroke() method can draw dashed and dotted lines as well as solid lines, and a canvas’s graphics state includes an array of numbers that serves as a “dash pattern” by specifying how many pixels to draw, then how many to omit. Unlike other line-drawing properties, the dash pattern is set and queried with the methods setLineDash() and getLineDash() instead of with a property. To specify a dotted dash pattern, you might use setLineDash() like this:
......@@ -2048,8 +2049,8 @@ This method is like bezierCurveTo(), but it uses a quadratic Bezier curve instea
You can use these methods to draw paths like those in Figure 15-10.
js7e 1509
Figure 15-10. Curved paths in a canvas
<Figures figure="15-10">Curved paths in a canvas</Figures>
Example 15-6 shows the code used to create Figure 15-10. The methods demonstrated in this code are some of the most complicated in the Canvas API; consult an online reference for complete details on the methods and their arguments.
Example 15-6. Adding curves to a path
......@@ -2147,8 +2148,8 @@ As we’ve noted, the default coordinate system of a canvas places the origin in
The setTransform() method allows you to set a canvas’s transformation matrix directly, but coordinate system transformations are usually easier to specify as a sequence of translations, rotations, and scaling operations. Figure 15-11 illustrates these operations and their effect on the canvas coordinate system. The program that produced the figure drew the same set of axes seven times in a row. The only thing that changed each time was the current transform. Notice that the transforms affect the text as well as the lines that are drawn.
js7e 1510
Figure 15-11. Coordinate system transformations
<Figures figure="15-11">Coordinate system transformations</Figures>
The translate() method simply moves the origin of the coordinate system left, right, up, or down. The rotate() method rotates the axes clockwise by the specified angle. (The Canvas API always specifies angles in radians. To convert degrees to radians, divide by 180 and multiply by Math.PI.) The scale() method stretches or contracts distances along the x or y axes.
Passing a negative scale factor to the scale() method flips that axis across the origin, as if it were reflected in a mirror. This is what was done in the lower left of Figure 15-11: translate() was used to move the origin to the bottom-left corner of the canvas, then scale() was used to flip the y axis around so that y coordinates increase as we go up the page. A flipped coordinate system like this is familiar from algebra class and may be useful for plotting data points on charts. Note, however, that it makes text difficult to read!
......@@ -2213,8 +2214,8 @@ c.restore(); // Restore the saved coordinate system
TRANSFORMATION EXAMPLE
Example 15-7 demonstrates the power of coordinate system transformations by using the translate(), rotate(), and scale() methods recursively to draw a Koch snowflake fractal. The output of this example appears in Figure 15-12, which shows Koch snowflakes with 0, 1, 2, 3, and 4 levels of recursion.
js7e 1511
Figure 15-12. Koch snowflakes
<Figures figure="15-12">Koch snowflakes</Figures>
The code that produces these figures is elegant, but its use of recursive coordinate system transformations makes it somewhat difficult to understand. Even if you don’t follow all the nuances, note that the code includes only a single invocation of the lineTo() method. Every single line segment in Figure 15-12 is drawn like this:
```js
c.lineTo(len, 0);
......@@ -2274,8 +2275,8 @@ c.stroke(); // Stroke this very complicated path
### 15.8.6 Clipping
After defining a path, you usually call stroke() or fill() (or both). You can also call the clip() method to define a clipping region. Once a clipping region is defined, nothing will be drawn outside of it. Figure 15-13 shows a complex drawing produced using clipping regions. The vertical stripe running down the middle and the text along the bottom of the figure were stroked with no clipping region and then filled after the triangular clipping region was defined.
js7e 1512
Figure 15-13. Unclipped strokes and clipped fills
<Figures figure="15-13">Unclipped strokes and clipped fills</Figures>
Figure 15-13 was generated using the polygon() method of Example 15-5 and the following code:
```js
// Define some drawing attributes
......@@ -2313,8 +2314,8 @@ These pixel manipulation methods provide very low-level access to the canvas. Th
Pixel manipulation methods are useful for implementing image processing. Example 15-8 shows how to create a simple motion blur or “smear” effect like that shown in Figure 15-14.
js7e 1513
Figure 15-14. A motion blur effect created by image processing
<Figures figure="15-14">A motion blur effect created by image processing</Figures>
The following code demonstrates getImageData() and putImageData() and shows how to iterate through and modify the pixel values in an ImageData object.
Example 15-8. Motion blur with ImageData
......@@ -2520,8 +2521,8 @@ When the user navigates to saved history states using the Back or Forward button
Example 15-9 is a simple web application—the number-guessing game pictured in Figure 15-15—that uses pushState() to save its history, allowing the user to “go back” to review or redo their guesses.
js7e 1514
Figure 15-15. A number-guessing game
<Figures figure="15-15">A number-guessing game</Figures>
Example 15-9. History management with pushState()
```html
<html><head><title>I'm thinking of a number...</title>
......@@ -3685,8 +3686,8 @@ This chapter on client-side JavaScript culminates with a long example that demon
The example is a program for displaying and exploring the Mandelbrot set, a complex fractal that includes beautiful images like the one shown in Figure 15-16.
js7e 1515
Figure 15-16. A portion of the Mandelbrot set
<Figures figure="15-16">A portion of the Mandelbrot set</Figures>
The Mandelbrot set is defined as the set of points on the complex plane, which, when put through a repeated process of complex multiplication and addition, produce a value whose magnitude remains bounded. The contours of the set are surprisingly complex, and computing which points are members of the set and which are not is computationally intensive: to produce a 500×500 image of the Mandelbrot set, you must individually compute the membership of each of the 250,000 pixels in your image. And to verify that the value associated with each pixel remains bounded, you may have to repeat the process of complex multiplication 1,000 times or more. (More iterations give more sharply defined boundaries for the set; fewer iterations produce fuzzier boundaries.) With up to 250 million steps of complex arithmetic required to produce a high-quality image of the Mandelbrot set, you can understand why using workers is a valuable technique. Example 15-14 shows the worker code we will use. This file is relatively compact: it is just the raw computational muscle for the larger program. Two things are worth noting about it, however:
The worker creates an ImageData object to represent the rectangular grid of pixels for which it is computing Mandelbrot set membership. But instead of storing actual pixel values in the ImageData, it uses a custom-typed array to treat each pixel as a 32-bit integer. It stores the number of iterations required for each pixel in this array. If the magnitude of the complex number computed for each pixel becomes greater than four, then it is mathematically guaranteed to grow without bounds from then on, and we say it has “escaped.” So the value this worker returns for each pixel is the number of iterations before the value escaped. We tell the worker the maximum number of iterations it should try for each value, and pixels that reach this maximum number are considered to be in the set.
......
......@@ -154,8 +154,8 @@ let o = new F(); // Create an object o of class F
o.constructor === F // => true: the constructor property specifies the class
Figure 9-1 illustrates this relationship between the constructor function, its prototype object, the back reference from the prototype to the constructor, and the instances created with the constructor.
js7e 0901
Figure 9-1. A constructor function, its prototype, and instances
<Figures figure="9-1">A constructor function, its prototype, and instances</Figures>
Notice that Figure 9-1 uses our Range() constructor as an example. In fact, however, the Range class defined in Example 9-2 overwrites the predefined Range.prototype object with an object of its own. And the new prototype object it defines does not have a constructor property. So instances of the Range class, as defined, do not have a constructor property. We can remedy this problem by explicitly adding a constructor to the prototype:
Range.prototype = {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册