Shape classes

Some JavaScript shape classes, with unit tests, of course

by Ray Toal

HTML

<script src="https://code.jquery.com/qunit/qunit-git.js"></script>
<link rel="stylesheet" href="https://code.jquery.com/qunit/qunit-git.css">
<div id="qunit"></div>
<div id="qunit-fixture"></div>

JavaScript

/*
 * A circle datatype.
 *
 * Synopsis:
 * let c = new Circle(10);
 * c.radius ==> 10
 * c.area() ==> 314.1592653589793
 * c.perimeter() ==> 62.83185307179586
 */
class Circle {
  constructor(r) {
    this.radius = r;
  }
  area() {
    return Math.PI * this.radius * this.radius;
  }  
  perimeter() {
    return 2 * Math.PI * this.radius;
  }
}

/*
 * A rectangle datatype.
 *
 * Synopsis:
 * let r = new Rectangle(5, 8);
 * r.length ==> 5
 * r.width ==> 8
 * r.area() ==> 40
 * r.perimeter() ==> 26
 */
class Rectangle {
  constructor(w, h) {
    this.width = w;
    this.height = h;
  }
  area() {
    return this.width * this.height;
  }
  perimeter() {
    return 2 * (this.width + this.height);
  }
}

/*
 * A polygon datatype.
 *
 * Synopsis:
 * let p = new Polygon([[0,0], [5,12], [5,0]]);
 * p.length ==> 3
 * p.points ==> [[0,0], [5,12], [5,0]]
 * p.area() ==> 30
 * p.perimeter() ==> 30
 *
 * PRECONDITION: The points must be entered in clockwise order and
 * the polygon should not be self-intersecting, otherwise the area()
 * function will almost certainly fail.
 *
 * LIMITATIONS: The constructor simply captures and stores the array
 * argument passed to it, so modifying the argument outside of the
 * polygon operations will have the side-effect of changing the polygon
 * itself.
 */
class Polygon {
  constructor(points) {
    this.points = points;
  }
  area() {
    let sum = 0;
    for (let i = 0, n = this.points.length, j = n - 1; i < n; j = i, i += 1) {
      let p = this.points[j], q = this.points[i];
      sum += (p[0] + q[0]) * (p[1] - q[1]);
    }
    return sum / 2;
  }
  perimeter() {
    let distance = (p, q) => {
      let dx = p[0] - q[0], dy = p[1] - q[1];
      return Math.sqrt(dx * dx + dy * dy);
    };
    let length = 0;
    for (let i = 0, n = this.points.length, j = n - 1; i < n; j = i, i += 1) {
      length += distance(this.points[j], this.points[i]);
    }
    return length;
  }
}

// TESTS
QUnit.test("Circle tests", t => {
  let c = new...