Stroke Style, Caps and Joins

lineWidth is centered on the path. lineCap is butt, round or square (the last two reach half a width past the end). lineJoin is miter, round or bevel; a miter longer than miterLimit (10) half-widths becomes a bevel. setLineDash([dash, gap]) dashes, and animating lineDashOffset makes "marching ants".

Caps against their endpoints, three joins, and dashesHTML
<canvas id="c" style="width:600px; height:104px"></canvas><script src="hidpi.js"></script>
<script>
  const ctx = hidpi(c), colors = ['#1f5f8b', '#3f7d3a', '#b5452f'];
  ctx.lineWidth = 16;
  ['butt', 'round', 'square'].forEach((cap, i) => {
    ctx.strokeStyle = colors[i];  ctx.lineCap = cap;  ctx.beginPath();
    ctx.moveTo(20 + i * 40, 25);  ctx.lineTo(20 + i * 40, 80);  ctx.stroke();
    ctx.lineJoin = ['miter', 'round', 'bevel'][i];  ctx.lineCap = 'butt';  ctx.beginPath();
    const x = 150 + i * 110;  ctx.moveTo(x, 85);  ctx.lineTo(x + 40, 20);
    ctx.lineTo(x + 80, 85);  ctx.stroke();
  });
  ctx.lineWidth = 1;  ctx.strokeStyle = '#263238';  ctx.strokeRect(0, 25, 125, 55); // ends
  ctx.setLineDash([12, 6]);  ctx.lineWidth = 4;  ctx.strokeStyle = '#e09a10';
  ctx.strokeRect(480, 20, 100, 66);
</script>
Browser output of Listing 2.6
Browser output of 6

Only the blue butt line ends on the guides. Use round joins for thick chart lines, or sharp data turns sprout miter spikes.

lineCap, lineJoin, setLineDash and marching ants with lineDashOffsetHTMLLive
<!doctype html>
<style>
  body { margin: 0; padding: 8px; background: #fafaf7; }
  canvas { width: 100%; max-width: 600px; height: 150px; display: block; background: #fff; border: 1px solid #ddd; }
</style>
<canvas id="c"></canvas>
<script>
  function hidpi(c, r = devicePixelRatio) {
    c.width = c.clientWidth * r;  c.height = c.clientHeight * r;
    const ctx = c.getContext('2d');  ctx.scale(r, r);  return ctx;
  }
  const ctx = hidpi(document.getElementById('c'));
  const colors = ['#1f5f8b', '#3f7d3a', '#b5452f'];

  function draw(time) {
    ctx.clearRect(0, 0, 600, 150);
    ctx.setLineDash([]);
    ctx.font = '11px sans-serif';  ctx.textAlign = 'center';
    ['butt', 'round', 'square'].forEach((cap, i) => {
      // Caps: round and square reach half a line width past the end point
      ctx.lineWidth = 16;  ctx.strokeStyle = colors[i];  ctx.lineCap = cap;
      ctx.beginPath();  ctx.moveTo(25 + i * 40, 35);  ctx.lineTo(25 + i * 40, 100);  ctx.stroke();
      ctx.fillStyle = '#263238';  ctx.fillText(cap, 25 + i * 40, 130);

      // Joins: miter (sharp), round, bevel (cut off)
      ctx.lineCap = 'butt';  ctx.lineJoin = ['miter', 'round', 'bevel'][i];
      const x = 160 + i * 105;
      ctx.beginPath();  ctx.moveTo(x, 105);  ctx.lineTo(x + 40, 30);  ctx.lineTo(x + 80, 105);
      ctx.stroke();
      ctx.fillText(ctx.lineJoin, x + 40, 130);
    });
    // Guides show where the paths really end
    ctx.lineWidth = 1;  ctx.strokeStyle = '#263238';  ctx.strokeRect(0.5, 35, 130, 65);

    // Marching ants: a dashed selection box whose dash offset moves over time
    ctx.setLineDash([12, 6]);  ctx.lineDashOffset = -time / 40;
    ctx.lineWidth = 4;  ctx.strokeStyle = '#e09a10';  ctx.lineJoin = 'miter';
    ctx.strokeRect(480, 30, 100, 76);
    ctx.fillText('setLineDash([12, 6])', 530, 130);
    requestAnimationFrame(draw);
  }
  requestAnimationFrame(draw);
</script>