Skip to content

Instantly share code, notes, and snippets.

@kselax
Last active December 8, 2018 17:40
Show Gist options
  • Save kselax/efba8783de7de386207aa4667564834d to your computer and use it in GitHub Desktop.
Save kselax/efba8783de7de386207aa4667564834d to your computer and use it in GitHub Desktop.
chapter 6 of eloquent JavaScript
// A vector type
// Write a class Vec that represents a vector in two-dimensional space. It takes
// x and y parameters (numbers), which it should save to properties of the same
// name.
// Give the Vec prototype two methods, plus and minus , that take another
// vector as a parameter and return a new vector that has the sum or difference
// of the two vectors’ ( this and the parameter) x and y values.
// Add a getter property length to the prototype that computes the length of
// the vector—that is, the distance of the point (x, y) from the origin (0, 0).
class Vec {
constructor(x, y) {
this.x = x
this.y = y
}
get length() {
return Math.sqrt(this.x * this.x + this.y * this.y)
}
}
Vec.prototype.plus = function(vec) {
return new Vec(this.x + vec.x, this.y + vec.y)
}
Vec.prototype.minus = function(vec) {
return new Vec(this.x - vec.x, this.y - vec.y)
}
const vec1 = new Vec(10, 15)
console.log(vec1); // { x: 10, y: 15}
const vec2 = new Vec(5, 10)
console.log(vec2); // { x: 5, y: 10}
const vec3 = vec1.plus(vec2)
console.log(vec3); // { x: 15, y: 25}
const vec4 = vec1.minus(vec2)
console.log(vec4); // { x: 5, y: 5}
console.log(vec4.length); // 7.0710678118654755
// Groups
// The standard JavaScript environment provides another data structure called
// Set . Like an instance of Map , a set holds a collection of values. Unlike Map , it
// does not associate other values with those—it just tracks which values are part
// of the set. A value can be part of a set only once—adding it again doesn’t have
// any effect.
// Write a class called Group (since Set is already taken). Like Set , it has add ,
// delete , and has methods. Its constructor creates an empty group, add adds
// a value to the group (but only if it isn’t already a member), delete removes
// its argument from the group (if it was a member), and has returns a Boolean
// value indicating whether its argument is a member of the group.
// Use the === operator, or something equivalent such as indexOf , to determine
// whether two values are the same.
// Give the class a static from method that takes an iterable object as argument
// and creates a group that contains all the values produced by iterating over it.
class Group {
constructor() {
this.val = []
}
add(e) {
if (this.val.indexOf(e) === -1) {
this.val.push(e)
}
}
delete(e) {
const index = this.val.indexOf(e)
if (index !== -1) {
this.val.splice(index, 1)
}
}
has(e) {
if (this.val.indexOf(e) === -1) return false
return true
}
static from(collection) {
let group = new Group
for (let value of collection) {
group.add(value)
}
return group
}
}
const g = new Group()
console.log(g); // Group { val: [] }
g.add(10)
g.add(15)
g.add(18)
console.log(g); // Group { val: [ 10, 15, 18 ] }
g.delete(15)
console.log(g); // Group { val: [ 10, 18 ] }
console.log(g.has(18)); // true
console.log(g.has(3)); // false
const ng = Group.from([1, 2, 3, 4, 5])
console.log(ng); // Group { val: [ 1, 2, 3, 4, 5 ] }
// Iterable groups
// Make the Group class from the previous exercise iterable. Refer to the section
// about the iterator interface earlier in the chapter if you aren’t clear on the
// exact form of the interface anymore.
// If you used an array to represent the group’s members, don’t just return the
// iterator created by calling the Symbol.iterator method on the array. That
// would work, but it defeats the purpose of this exercise.
// It is okay if your iterator behaves strangely when the group is modified during
// iteration.
class Group {
constructor() {
this.val = []
}
add(e) {
if (this.val.indexOf(e) === -1) {
this.val.push(e)
}
}
delete(e) {
const index = this.val.indexOf(e)
if (index !== -1) {
this.val.splice(index, 1)
}
}
has(e) {
if (this.val.indexOf(e) === -1) return false
return true
}
static from(collection) {
let group = new Group
for (let value of collection) {
group.add(value)
}
return group
}
[Symbol.iterator]() {
return new GroupIterator(this)
}
}
class GroupIterator {
constructor(obj) {
this.val = obj.val
this.position = 0
}
next() {
if (this.val.length <= this.position) {
return {done: true}
} else {
return {value: this.val[this.position++], done: false}
}
}
}
for (let v of Group.from(['a', 'b', 'c'])) {
console.log('v = ', v);
}
// Borrowing a method
// Earlier in the chapter I mentioned that an object’s hasOwnProperty can be
// used as a more robust alternative to the in operator when you want to ignore
// the prototype’s properties. But what if your map needs to include the word
// "hasOwnProperty" ? You won’t be able to call that method anymore because
// the object’s own property hides the method value.
// Can you think of a way to call hasOwnProperty on an object that has its own
// property by that name?
class Test {
print() {
console.log('Test');
}
hasOwnProperty() {
console.log('here we are');
}
has(prop) {
return super.hasOwnProperty(prop)
}
}
const obj = new Test()
obj.print = () => console.log('hello');
console.log(obj.hasOwnProperty('print'));
obj.print()
console.log(obj.has('print'));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment