Last active
December 8, 2018 17:40
-
-
Save kselax/efba8783de7de386207aa4667564834d to your computer and use it in GitHub Desktop.
chapter 6 of eloquent JavaScript
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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 ] } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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