diff --git a/00/Hello.js b/00/Hello.js new file mode 100644 index 0000000..5a1baa2 --- /dev/null +++ b/00/Hello.js @@ -0,0 +1,8 @@ +function hello(name){ + if(typeof name === "undefined"){ + return "Hello!"; + } else { + return "Hello, " + name + "!"; + } +} +// diff --git a/00/HelloSpec.js b/00/HelloSpec.js new file mode 100644 index 0000000..224cf8c --- /dev/null +++ b/00/HelloSpec.js @@ -0,0 +1,10 @@ +// talk about function +describe("Hello", function() { + it("says hello", function() { + expect(hello()).toEqual("Hello!"); + }); + + it("says hello to someone", function() { + expect(hello("Fred")).toEqual("Hello, Fred!"); + }); +}); diff --git a/01/properties.js b/01/properties.js new file mode 100644 index 0000000..eb8097d --- /dev/null +++ b/01/properties.js @@ -0,0 +1,28 @@ +function setPropertiesOnObjLiteral(obj) { + obj.x = 7; + obj.y = 8; + obj.onePlus = function(addToMe) { + return addToMe + 1; + }; +} + +function setPropertiesOnArrayObj(obj) { + obj.hello = function() { + return "Hello!"; + }; + obj['full'] = "stack"; + obj[0] = 5; + obj.twoTimes = function(doubleMe) { + return doubleMe * 2; + }; +} + +function setPropertiesOnFunctionObj(obj) { + obj.year = 2015; + obj.divideByTwo = function(halveMe) { + return halveMe / 2; + }; + obj.prototype.helloWorld = function() { + return "Hello World"; + }; +} \ No newline at end of file diff --git a/01/propertiesSpec.js b/01/propertiesSpec.js new file mode 100644 index 0000000..27c1fe9 --- /dev/null +++ b/01/propertiesSpec.js @@ -0,0 +1,107 @@ +describe("Properties on Object Literal", function() { + var object; + + // beforeEach is a Jasmine helper that runs + // the code inside the passed function before each test below + // It's helpful for not having to repeat yourself constantly + // in your test specs + beforeEach(function() { + + // for each test, create a new empty object + object = {}; + + // then run the setPropertiesOnObjLiteral function that you've written in properties.js + setPropertiesOnObjLiteral(object); + }); + + describe("setPropertiesOnObjLiteral", function() { + it("sets x to 7", function() { + expect(object.x).toEqual(7); + }); + + it("sets y to 8 (and we can use a string to access it)", function() { + expect(object['y']).toEqual(8); + }); + + it("sets the property 'onePlus' to a function that adds one to its parameter", function() { + expect(object.onePlus(4)).toEqual(5); + expect(object['onePlus'](123)).toEqual(124); + }); + }); +}); + + +// Now let's explore the idea of using Arrays instead of Objects. +// One of the coolest things about JavaScript is that Arrays are just +// a specific type of Object that has more features. Everything that you can do +// with objects, you can also do with arrays. +describe("Properties on an Array Object", function() { + var arrayObject; + + beforeEach(function() { + arrayObject = []; + setPropertiesOnArrayObj(arrayObject); + }); + + describe("setPropertiesOnArrayObj", function() { + it("sets the property `hello` to a function that returns the string `Hello!`", function() { + expect(arrayObject.hello()).toEqual("Hello!"); + }); + + it("sets the property `full` to stack (and we can use a string to access it)", function() { + expect(arrayObject['full']).toEqual("stack"); + }); + + it("accesses the zeroth index value in the array", function() { + expect(arrayObject[0]).toEqual(5); + }); + + it("sets the property 'twoTimes' to a function that multiplies its parameter by 1", function() { + expect(arrayObject.twoTimes(4)).toEqual(8); + expect(arrayObject['twoTimes'](123)).toEqual(246); + }); + + }); +}); + + +// It's the same with functions, they're also Objects. +// +// This is an idea that we'll explore a lot more when we get to inheritance in the +// Mammals exercise. +describe("Properties on a Function Object", function() { + var functionObject; + + beforeEach(function() { + functionObject = function() { + return "I am a function object, all functions are objects! Function can have their own properties too!"; + }; + setPropertiesOnFunctionObj(functionObject); + }); + + describe("`functionObject` function", function() { + it("returns the proper string the `functionObject` function returns declared in the beforeEach Function above", function() { + expect(functionObject()).toEqual("I am a function object, all functions are objects! Function can have their own properties too!"); + }); + }); + + describe("setPropertiesOnFunctionObj", function() { + it("sets year to 2015", function() { + expect(functionObject.year).toEqual(2015); + }); + + it("sets `divideByTwo` to a function that accepts a number and returns the value divided by two ", function() { + expect(functionObject.divideByTwo(6)).toEqual(3); + }) + + // Whenever you define a function in JavaScript, that "function object" also has a built-in property + // similar to `Array.length`. This property is called `prototype` and it has some special behavior + // when used in conjunction with the `new` keyword. We'll cover this later in _Mammals_ + // + // However, just like any other object, we can do whatever we want to this `prototype` object + it("adds a property to the existing prototype object only on Function Objects", function() { + expect(functionObject.prototype.helloWorld()).toEqual("Hello World"); + }); + }); + +}); diff --git a/02/calculator.js b/02/calculator.js new file mode 100644 index 0000000..5f129e3 --- /dev/null +++ b/02/calculator.js @@ -0,0 +1,14 @@ +var createCalculator = function() { + var returnMe = {}; + returnMe.myValue = 0; + returnMe.value = function() { + return this.myValue; + }; + returnMe.add = function(addValue) { + this.myValue += addValue; + }; + returnMe.subtract = function(minusValue) { + this.myValue -= minusValue; + } + return returnMe; +} \ No newline at end of file diff --git a/02/calculatorSpec.js b/02/calculatorSpec.js new file mode 100644 index 0000000..4a67f75 --- /dev/null +++ b/02/calculatorSpec.js @@ -0,0 +1,49 @@ +// In this exercise we're going to create a calculator object +// that can perform certain basic mathematic operations. +// +// We'll be using a pattern called the factory pattern where +// our function creates an object tailored to our needs. This function +// is just like the one we built in *01_properties*, except now we're +// creating some useful functions add +describe("Create a Calculator", function() { + var calculator; + + // Here we're just calling the `createCalculator` function, it returns + // a calculator object. + beforeEach(function() { + calculator = createCalculator(); + }); + + it("initially has 0", function() { + expect(calculator.value()).toEqual(0); + }); + + it("can add a number", function() { + calculator.add(2); + expect(calculator.value()).toEqual(2); + }); + + it("can add two numbers", function() { + calculator.add(2); + calculator.add(3); + expect(calculator.value()).toEqual(5); + }); + + it("can add many numbers", function() { + calculator.add(2); + calculator.add(3); + calculator.add(4); + expect(calculator.value()).toEqual(9); + }); + + it("can subtract a number", function() { + calculator.subtract(2); + expect(calculator.value()).toEqual(-2); + }); + + it("can add and subtract", function() { + calculator.add(3); + calculator.subtract(2); + expect(calculator.value()).toEqual(1); + }); +}); diff --git a/03/RPNCalculator.js b/03/RPNCalculator.js new file mode 100644 index 0000000..49221b0 --- /dev/null +++ b/03/RPNCalculator.js @@ -0,0 +1,55 @@ +var RPNCalculator = function() { + this.stack = new Array(); +} + +RPNCalculator.prototype.value = function() { + return this.stack[this.stack.length - 1]; +}; + +RPNCalculator.prototype.push = function(pushMe) { + this.stack.push(pushMe); +} + +RPNCalculator.prototype.plus = function() { + if(this.stack.length >= 2) { + var temp1 = this.stack.pop(); + var temp2 = this.stack.pop(); + var temp3 = temp1+temp2; + this.stack.push(temp3); + } else { + throw "rpnCalculator is empty"; + } +} + +RPNCalculator.prototype.minus = function() { + if(this.stack.length >= 2) { + var temp1 = this.stack.pop(); + var temp2 = this.stack.pop(); + var temp3 = temp2-temp1; + this.stack.push(temp3); + } else { + throw "rpnCalculator is empty"; + } +} + +RPNCalculator.prototype.divide = function() { + if(this.stack.length >= 2) { + var temp1 = this.stack.pop(); + var temp2 = this.stack.pop(); + var temp3 = temp2/temp1; + this.stack.push(temp3); + } else { + throw "rpnCalculator is empty"; + } +} + +RPNCalculator.prototype.times = function() { + if(this.stack.length >= 2) { + var temp1 = this.stack.pop(); + var temp2 = this.stack.pop(); + var temp3 = temp1*temp2; + this.stack.push(temp3); + } else { + throw "rpnCalculator is empty"; + } +} \ No newline at end of file diff --git a/03/rpnCalculatorSpec.js b/03/rpnCalculatorSpec.js new file mode 100644 index 0000000..0013e78 --- /dev/null +++ b/03/rpnCalculatorSpec.js @@ -0,0 +1,81 @@ +// See http://en.wikipedia.org/wiki/Reverse_Polish_notation +// +// constructor functions, new keyword, how it relates to this +describe("Calculator using reverse polish notation", function() { + var rpnCalculator; + + beforeEach(function() { + rpnCalculator = new RPNCalculator(); + }); + + it("adds two numbers", function() { + rpnCalculator.push(2); + rpnCalculator.push(3); + rpnCalculator.plus(); + expect(rpnCalculator.value()).toEqual(5); + }); + + it("adds three numbers", function() { + rpnCalculator.push(2); + rpnCalculator.push(3); + rpnCalculator.push(4); + rpnCalculator.plus(); + expect(rpnCalculator.value()).toEqual(7); + rpnCalculator.plus(); + expect(rpnCalculator.value()).toEqual(9); + }); + + it("adds and subtracts", function() { + rpnCalculator.push(2); + rpnCalculator.push(3); + rpnCalculator.push(4); + rpnCalculator.minus(); + expect(rpnCalculator.value()).toEqual(-1); + rpnCalculator.plus(); + expect(rpnCalculator.value()).toEqual(1); + }); + + it("multiplies and divides", function() { + rpnCalculator.push(2); + rpnCalculator.push(3); + rpnCalculator.push(4); + rpnCalculator.divide(); + expect(rpnCalculator.value()).toEqual(0.75); + rpnCalculator.times(); + expect(rpnCalculator.value()).toEqual(1.5); + }); + + it("fails informatively when there's not enough values stashed away", function() { + expect(function() { + rpnCalculator.plus(); + }).toThrow("rpnCalculator is empty"); + + expect(function() { + rpnCalculator.minus(); + }).toThrow("rpnCalculator is empty"); + + expect(function() { + rpnCalculator.times(); + }).toThrow("rpnCalculator is empty"); + + expect(function() { + rpnCalculator.divide(); + }).toThrow("rpnCalculator is empty"); + }); + + it("All methods should be on the RPNCalculator.prototype", function() { + expect(typeof RPNCalculator.prototype.plus).toEqual("function"); + expect(typeof RPNCalculator.prototype.minus).toEqual("function"); + expect(typeof RPNCalculator.prototype.divide).toEqual("function"); + expect(typeof RPNCalculator.prototype.value).toEqual("function"); + }); + + // Here we're using the `instanceof` keyword in JS so see if `rpnCalculator` is + // an "instance" of capital RPNCalculator. `instanceof` tests to see if + // an 'internal prototype' (`__proto__`) in the chain of `rpnCalculator` matches the `RPNCalculator.prototype` object. + it("the rpnCalculator object should be an instance of the RPNCalculator Constructor", function() { + expect(rpnCalculator instanceof RPNCalculator).toEqual(true); + }); + + +}); diff --git a/04/loops.js b/04/loops.js new file mode 100644 index 0000000..1463438 --- /dev/null +++ b/04/loops.js @@ -0,0 +1,104 @@ +var repeat = function(repeatMe, num) { + var returnMe = ""; + for(; num; num--) { + returnMe+=repeatMe; + } + return returnMe; +}; + +var sum = function(sumMe) { + var returnMe = 0; + for(var i = 0; i