To begin, find the file 'topics/0_asserts.js', and complete the tests.
+
+
test markup, will be hidden
+
+
diff --git a/topics/about_asserts.js b/topics/0_asserts.js
similarity index 54%
rename from topics/about_asserts.js
rename to topics/0_asserts.js
index f94dde46..3f82c7e0 100644
--- a/topics/about_asserts.js
+++ b/topics/0_asserts.js
@@ -1,5 +1,8 @@
-
-module("About Asserts (topics/about_asserts.js)");
+/*
+ These exercises use the QUnit test suite. It contains of three different
+ functions to test for expected values. Fill in the values to see how they work!
+*/
+module("About Asserts (topics/0_asserts.js)");
test("ok", function() {
ok(__, 'what will satisfy the ok assertion?');
diff --git a/topics/10_reflection.js b/topics/10_reflection.js
new file mode 100644
index 00000000..ee9f3b6f
--- /dev/null
+++ b/topics/10_reflection.js
@@ -0,0 +1,22 @@
+module("About Reflection (topics/10_reflection.js)");
+
+test("typeof", function() {
+ equals(typeof({}), __, 'what is the type of an empty object?');
+ equals(typeof('apple'), __, 'what is the type of a string?');
+ equals(typeof(-5), __, 'what is the type of -5?');
+ equals(typeof(false), __, 'what is the type of false?');
+});
+
+test("property enumeration", function() {
+ var keys = [];
+ var values = [];
+ var person = {name: 'Amory Blaine', age: 102, unemployed: true};
+ for(propertyName in person) {
+ keys.push(propertyName);
+ values.push(person[propertyName]);
+ }
+ ok(keys.equalTo(['__','__','__']), 'what are the property names of the object?');
+ ok(values.equalTo(['__',__,__]), 'what are the property values of the object?');
+});
+
+
diff --git a/topics/about_prototype_chain.js b/topics/11_prototype_chain.js
similarity index 96%
rename from topics/about_prototype_chain.js
rename to topics/11_prototype_chain.js
index e215b8a7..8b60dbd2 100644
--- a/topics/about_prototype_chain.js
+++ b/topics/11_prototype_chain.js
@@ -1,7 +1,7 @@
// demonstrate objects prototype chain
// https://developer.mozilla.org/en/JavaScript/Guide/Inheritance_and_the_prototype_chain
-module("About Prototype Chain (topics/about_prototype_chain.js)");
+module("About Prototype Chain (topics/11_prototype_chain.js)");
var father = {
b: 3,
diff --git a/topics/about_prototypal_inheritance.js b/topics/12_prototypal_inheritance.js
similarity index 67%
rename from topics/about_prototypal_inheritance.js
rename to topics/12_prototypal_inheritance.js
index b2d152c6..5235583b 100644
--- a/topics/about_prototypal_inheritance.js
+++ b/topics/12_prototypal_inheritance.js
@@ -1,7 +1,7 @@
// demonstrate the effect of modifying an objects prototype before and after the object is constructed
-module("About Prototypal Inheritance (topics/about_prototypal_inheritance.js)");
+module("About Prototypal Inheritance (topics/12_prototypal_inheritance.js)");
// this 'class' pattern defines a class by its constructor
var Mammal = function(name) {
@@ -37,24 +37,3 @@ test("calling functions added to a prototype after an object was created", funct
// for the following statement asks the paul object to call a function that was added to the Mammal prototype after paul was constructed.
equals(paul.numberOfLettersInName(), __, "how long is Paul's name?");
});
-
-// helper function for inheritance.
-// From https://developer.mozilla.org/en/JavaScript/Guide/Inheritance_Revisited
-function extend(child, supertype){
- child.prototype = supertype.prototype;
-}
-
-// "Subclass" Mammal
-function Bat(name, wingspan) {
- Mammal.call(this, name);
- this.wingspan = wingspan;
-}
-
-// configure inheritance
-extend(Bat, Mammal);
-
-test("Inheritance", function() {
- var lenny = new Bat("Lenny", "1.5m");
- equals(lenny.sayHi(), __, "what does Lenny say?");
- equals(lenny.wingspan, __, "what is Lenny's wingspan?");
-});
diff --git a/topics/13_functions_and_closure.js b/topics/13_functions_and_closure.js
new file mode 100644
index 00000000..b5b9758f
--- /dev/null
+++ b/topics/13_functions_and_closure.js
@@ -0,0 +1,35 @@
+
+module("About Functions And Closure (topics/13_functions_and_closure.js)");
+
+test("defining functions directly", function() {
+ var result = "a";
+ function changeResult() {
+ // the ability to access a variables defined in the same scope as the function is known as 'closure'
+ result = "b";
+ };
+ changeResult();
+ equals(result, __, 'what is the value of result?');
+});
+
+test("assigning functions to variables", function() {
+ var triple = function(input) {
+ return input * 3;
+ };
+ equals(triple(4), __, 'what is triple 4?');
+});
+
+test("self invoking functions", function() {
+ var publicValue = "shared";
+
+ // self invoking functions are used to provide scoping and to alias variables
+ (function(pv) {
+ var secretValue = "password";
+ equals(pv, __, 'what is the value of pv?');
+ equals(typeof(secretValue), "__", "is secretValue available in this context?");
+ equals(typeof(publicValue), "__", "is publicValue available in this context?");
+ })(publicValue);
+
+ equals(typeof(secretValue), "__", "is secretValue available in this context?");
+ equals(typeof(publicValue), "__", "is publicValue available in this context?");
+});
+
diff --git a/topics/about_this.js b/topics/14_this.js
similarity index 95%
rename from topics/about_this.js
rename to topics/14_this.js
index cad5546e..303a5def 100644
--- a/topics/about_this.js
+++ b/topics/14_this.js
@@ -1,4 +1,4 @@
-module("About this (topics/about_this.js)");
+module("About this (topics/14_this.js)");
test("'this' inside a method", function () {
var person = {
diff --git a/topics/about_regular_expressions.js b/topics/15_regular_expressions.js
similarity index 92%
rename from topics/about_regular_expressions.js
rename to topics/15_regular_expressions.js
index 8d409fca..1fcaed63 100644
--- a/topics/about_regular_expressions.js
+++ b/topics/15_regular_expressions.js
@@ -1,5 +1,5 @@
-module("About Regular Expressions (topics/about_regular_expressions.js)");
+module("About Regular Expressions (topics/15_regular_expressions.js)");
test("exec", function() {
var numberFinder = /(\d).*(\d)/;
diff --git a/topics/1_operators.js b/topics/1_operators.js
new file mode 100644
index 00000000..3483096f
--- /dev/null
+++ b/topics/1_operators.js
@@ -0,0 +1,17 @@
+
+module("About Operators (topics/1_operators.js)");
+
+test("logic", function(){
+ equals(true && true, __, "and");
+ equals(true || false, __, "or");
+});
+
+test("plus", function() {
+ // The plus operator works for nearly every datatype.
+ // But be careful, the results may be strange for everything
+ // else than strings and numbers.
+ equals(5+5, __, 'plus with numeric values');
+ equals("a" + "string", '__', 'string concatenation');
+ // Something unexecpected, better use Array.concat.
+ equals([1,2] + [3,4], '__', 'plus with arrays');
+});
diff --git a/topics/2_equality.js b/topics/2_equality.js
new file mode 100644
index 00000000..7a363d6a
--- /dev/null
+++ b/topics/2_equality.js
@@ -0,0 +1,32 @@
+/*
+ There are two differant operators to tests for
+ equality in JavaScript:
+ 1) ==, !=
+ 2) ===, !==
+ The first one does type coercion if the operands are
+ not of the same type. This leads to bugs which are very
+ hard to find. The rules for the type coercion are complicated
+ and unmemorable. So always use triple equals instead!
+*/
+module("About Equality (topics/2_equality.js)");
+
+test("equality without type coercion", function() {
+ ok(3 === __, 'what is exactly equal to 3?');
+});
+
+test("equality with type coercion", function() {
+ ok(3 == "__", 'what string is equal to 3, with type coercion?');
+});
+
+test("why type coercion is bad", function() {
+ // Can you guess all of them?
+ equals(0 == '', __);
+ equals('' == '0', __);
+ equals(0 == [0], __);
+ equals(0 == false, __);
+ equals(',,,' == new Array(4), __);
+});
+
+test("string literals", function() {
+ equals("frankenstein", '__', "quote types are interchangable, but must match.");
+});
diff --git a/topics/about_truthyness.js b/topics/3_truthyness.js
similarity index 90%
rename from topics/about_truthyness.js
rename to topics/3_truthyness.js
index 9c3f2319..c47d6b2c 100644
--- a/topics/about_truthyness.js
+++ b/topics/3_truthyness.js
@@ -1,5 +1,5 @@
-module("About Truthyness (topics/about_truthyness.js)");
+module("About Truthyness (topics/3_truthyness.js)");
test("truthyness of positive numbers", function() {
var oneIsTruthy = 1 ? true : false;
diff --git a/topics/4_assignment.js b/topics/4_assignment.js
new file mode 100644
index 00000000..d82e742f
--- /dev/null
+++ b/topics/4_assignment.js
@@ -0,0 +1,53 @@
+
+module("About Assignment (topics/4_assignment.js)");
+
+test("local variables", function() {
+ var temp = __;
+ equals(1, temp, "Assign a value to the variable temp");
+});
+
+test("no block scope", function() {
+ // JavaScript has no block scope like Java, but function scope.
+ // It's best to define all vars at the top of a function to avoid confusion
+ var isInnerVariableDefined = true;
+ if(true) {
+ var innerVariable = 5;
+ }
+ try {
+ innerVariable
+ } catch(e){
+ isInnerVariableDefined = false;
+ }
+ equals(isInnerVariableDefined, true, "there is no block scope");
+});
+
+test("function scope", function() {
+ var outerVariable = "outer";
+
+ // this is a self-invoking function. Notice that it calls itself at the end ().
+ (function() {
+ var innerVariable = "inner";
+ equals(outerVariable, __, 'is outerVariable defined in this scope?');
+ equals(innerVariable, __, 'is innerVariable defined in this scope?');
+ })();
+
+ equals(outerVariable, __, 'is outerVariable defined in this scope?');
+ var isInnerVariableDefined = true;
+ try {
+ innerVariable
+ } catch(e) {
+ isInnerVariableDefined = false;
+ }
+ equals(isInnerVariableDefined, __, 'is innerVariable defined in this scope?');
+});
+
+temp = 1;
+test("global variables", function() {
+ //If you try to use a variable before declaring it, JavaScript assumes that you
+ //meant the global context. The top level object is the window object, so your
+ //variable becomes a property of that object. Most of the time this is not intended
+ //by the programmer, so they introduced "use strict" in ES5. If you really want
+ //to make a global var use windows.myVar = value instead, but make sure not to
+ //override any existing properties!
+ equals(temp, window.__, 'global variables are assigned to the window object');
+});
diff --git a/topics/about_control_structures.js b/topics/5_control_structures.js
similarity index 89%
rename from topics/about_control_structures.js
rename to topics/5_control_structures.js
index 84e1f161..3b2e1230 100644
--- a/topics/about_control_structures.js
+++ b/topics/5_control_structures.js
@@ -1,5 +1,5 @@
-module("About Control Structures (topics/about_control_structures.js)");
+module("About Control Structures (topics/5_control_structures.js)");
test("if", function() {
var isPositive = false;
@@ -18,7 +18,7 @@ test("for", function() {
});
test("for in", function() {
- // this syntax will be explained in about objects
+ // this syntax will be explained in 8_objects
var person = {
name: "Amory Blaine",
age: 102
@@ -69,6 +69,7 @@ test("switch default case", function() {
});
test("null coallescion", function() {
+ //assigns the first value if it's "truthy", else the second value
var result = null || "a value";
equals(result, __, 'what is the value of result?');
});
diff --git a/topics/about_strings.js b/topics/6_strings.js
similarity index 64%
rename from topics/about_strings.js
rename to topics/6_strings.js
index 68fa6894..5c08c94c 100644
--- a/topics/about_strings.js
+++ b/topics/6_strings.js
@@ -1,5 +1,5 @@
-module("About Strings (topics/about_strings.js)");
+module("About Strings (topics/6_strings.js)");
test("delimiters", function() {
var singleQuotedString = 'apple';
@@ -18,17 +18,9 @@ test("character Type", function() {
equals(characterType, __, 'Javascript has no character type');
});
-test("escape character", function() {
- var stringWithAnEscapedCharacter = "\u0041pple";
- equals(stringWithAnEscapedCharacter, __, 'what is the value of stringWithAnEscapedCharacter?');
-});
-
test("string.length", function() {
var fruit = "apple";
equals(fruit.length, __, 'what is the value of fruit.length?');
});
-test("slice", function() {
- var fruit = "apple pie";
- equals(fruit.slice(0,5), __, 'what is the value of fruit.slice(0,5)?');
-});
+
diff --git a/topics/about_numbers.js b/topics/7_numbers.js
similarity index 91%
rename from topics/about_numbers.js
rename to topics/7_numbers.js
index 672f3318..75f50f05 100644
--- a/topics/about_numbers.js
+++ b/topics/7_numbers.js
@@ -1,5 +1,5 @@
-module("About Numbers (topics/about_numbers.js)");
+module("About Numbers (topics/7_numbers.js)");
test("types", function() {
var typeOfIntegers = typeof(6);
diff --git a/topics/about_objects.js b/topics/8_objects.js
similarity index 96%
rename from topics/about_objects.js
rename to topics/8_objects.js
index 35185b32..7515af0a 100644
--- a/topics/about_objects.js
+++ b/topics/8_objects.js
@@ -1,5 +1,5 @@
-module("About Objects (topics/about_objects.js)");
+module("About Objects (topics/8_objects.js)");
test("object type", function() {
var empty_object = {};
diff --git a/topics/about_arrays.js b/topics/9_arrays.js
similarity index 71%
rename from topics/about_arrays.js
rename to topics/9_arrays.js
index ab74a6c4..6cbc52f1 100644
--- a/topics/about_arrays.js
+++ b/topics/9_arrays.js
@@ -1,5 +1,5 @@
-module("About Arrays (topics/about_arrays.js)");
+module("About Arrays (topics/9_arrays.js)");
test("array literal syntax and indexing", function() {
var favouriteThings = ["cellar door", 42, true]; // note that array elements do not have to be of the same type
@@ -17,13 +17,6 @@ test("length", function() {
equals(collection.length, __, 'what is the length of the collection array?');
});
-test("splice", function() {
- var daysOfWeek = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'];
- var workingWeek = daysOfWeek.splice(__, __);
- ok(workingWeek.equalTo([__]), 'what is the value of workingWeek?');
- ok(daysOfWeek.equalTo([__]), 'what is the value of daysOfWeek?');
-});
-
test("stack methods", function() {
var stack = [];
stack.push("first");
diff --git a/topics/about_assignment.js b/topics/about_assignment.js
deleted file mode 100644
index 3b5c9831..00000000
--- a/topics/about_assignment.js
+++ /dev/null
@@ -1,12 +0,0 @@
-
-module("About Assignment (topics/about_assignment.js)");
-
-test("local variables", function() {
- var temp = __;
- equals(1, temp, "Assign a value to the variable temp");
-});
-
-test("global variables", function() {
- temp = 1;
- equals(temp, window.__, 'global variables are assigned to the window object');
-});
diff --git a/topics/about_equality.js b/topics/about_equality.js
deleted file mode 100644
index 797a653e..00000000
--- a/topics/about_equality.js
+++ /dev/null
@@ -1,22 +0,0 @@
-
-module("About Equality (topics/about_equality.js)");
-
-test("numeric equality", function() {
- equals(3 + __, 7, 'hmmmm?');
-});
-
-test("string equality", function() {
- equals("3" + __, "37", "concatenate the strings");
-});
-
-test("equality without type coercion", function() {
- ok(3 === __, 'what is exactly equal to 3?');
-});
-
-test("equality with type coercion", function() {
- ok(3 == "__", 'what string is equal to 3, with type coercion?');
-});
-
-test("string literals", function() {
- equals("frankenstein", '__', "quote types are interchangable, but must match.");
-});
diff --git a/topics/about_functions_and_closure.js b/topics/about_functions_and_closure.js
deleted file mode 100644
index ebe69740..00000000
--- a/topics/about_functions_and_closure.js
+++ /dev/null
@@ -1,75 +0,0 @@
-
-module("About Functions And Closure (topics/about_functions_and_closure.js)");
-
-test("defining functions directly", function() {
- var result = "a";
- function changeResult() {
- // the ability to access a variables defined in the same scope as the function is known as 'closure'
- result = "b";
- };
- changeResult();
- equals(result, __, 'what is the value of result?');
-});
-
-test("assigning functions to variables", function() {
- var triple = function(input) {
- return input * 3;
- };
- equals(triple(4), __, 'what is triple 4?');
-});
-
-test("self invoking functions", function() {
- var publicValue = "shared";
-
- // self invoking functions are used to provide scoping and to alias variables
- (function(pv) {
- var secretValue = "password";
- equals(pv, __, 'what is the value of pv?');
- equals(typeof(secretValue), "__", "is secretValue available in this context?");
- equals(typeof(publicValue), "__", "is publicValue available in this context?");
- })(publicValue);
-
- equals(typeof(secretValue), "__", "is secretValue available in this context?");
- equals(typeof(publicValue), "__", "is publicValue available in this context?");
-});
-
-test("arguments array", function() {
- var add = function() {
- var total = 0;
- for(var i = 0; i < arguments.length; i++) {
- // complete the implementation of this method so that it returns the sum of its arguments
- }
- // __
- };
-
- equals(add(1,2,3,4,5), 15, "add 1,2,3,4,5");
- equals(add(4,7,-2), 9, "add 1,2,3,4,5");
-});
-
-test("using call to invoke function",function(){
- var invokee = function( message ){
- return this + message;
- };
-
- //another way to invoke a function is to use the call function which allows
- //you to set the callers "this" context. Call can take any number of arguments:
- //the first one is always the context that this should be set to in the called
- //function, and the arguments to be sent to the function,multiple arguments are separated by commas.
- var result = invokee.call("I am this!", "Where did it come from?");
-
- equals(result,__,"what will the value of invokee's this be?");
-});
-
-test("using apply to invoke function",function(){
- var invokee = function( message1, message2 ){
- return this + message1 + message2;
- };
-
- //similar to the call function is the apply function. Apply only has two
- //arguments: the first is the context that this should be set to in the called
- //function and and array of arguments to be passed into the called function.
- var result = invokee.apply("I am this!", ["I am arg1","I am arg2"]);
-
- equals(result,__,"what will the value of invokee's this be?");
-});
-
diff --git a/topics/about_operators.js b/topics/about_operators.js
deleted file mode 100644
index 09df716b..00000000
--- a/topics/about_operators.js
+++ /dev/null
@@ -1,47 +0,0 @@
-
-module("About Operators (topics/about_operators.js)");
-
-test("addition", function() {
- var result = 0;
- //starting i at 0, add i to result and increment i by 1 until i is equal to 5
- for (var i = 0; i <= 5; i++) {
- result = result + i;
- }
- equals(result, __, "What is the value of result?");
-});
-
-test("assignment addition", function() {
- var result = 0;
- for (var i = 0; i <=5; i++) {
- //the code below is just like saying result = result + i; but is more concise
- result += i;
- }
- equals(result, __, "What is the value of result?");
-});
-
-test("subtraction", function() {
- var result = 5;
- for (var i = 0; i <= 2; i++) {
- result = result - i;
- }
- equals(result, __, "What is the value of result?");
-});
-
-test("assignment subtraction", function() {
- var result = 5;
- for (var i = 0; i <= 2; i++) {
- result -= i;
- }
- equals(result, __, "What is the value of result?");
-});
-
-//Assignment operators are available for multiplication and division as well
-//let's do one more, the modulo operator, used for showing division remainder
-
-test("modulus", function() {
- var result = 10;
- var x = 5;
- //again this is exactly the same as result = result % x
- result %= x;
- equals(result, __, "What is the value of result?");
-});
diff --git a/topics/about_reflection.js b/topics/about_reflection.js
deleted file mode 100644
index 30b716c1..00000000
--- a/topics/about_reflection.js
+++ /dev/null
@@ -1,67 +0,0 @@
-module("About Reflection (topics/about_reflection.js)");
-
-var A = function() {
- this.aprop = "A";
-};
-
-var B = function() {
- this.bprop = "B";
-};
-
-B.prototype = new A();
-
-test("typeof", function() {
- equals(typeof({}), __, 'what is the type of an empty object?');
- equals(typeof('apple'), __, 'what is the type of a string?');
- equals(typeof(-5), __, 'what is the type of -5?');
- equals(typeof(false), __, 'what is the type of false?');
-});
-
-test("property enumeration", function() {
- var keys = [];
- var values = [];
- var person = {name: 'Amory Blaine', age: 102, unemployed: true};
- for(propertyName in person) {
- keys.push(propertyName);
- values.push(person[propertyName]);
- }
- ok(keys.equalTo(['__','__','__']), 'what are the property names of the object?');
- ok(values.equalTo(['__',__,__]), 'what are the property values of the object?');
-});
-
-test("hasOwnProperty", function() {
- var b = new B();
-
- var keys = [];
- for (propertyName in b) {
- keys.push(propertyName);
- }
- equals(keys.length, __, 'how many elements are in the keys array?');
- ok(keys.equalTo([__, __]), 'what are the properties of the array?');
-
- // hasOwnProperty returns true if the parameter is a property directly on the object,
- // but not if it is a property accessible via the prototype chain.
- var ownKeys = [];
- for(propertyName in b) {
- if (b.hasOwnProperty(propertyName)) {
- ownKeys.push(propertyName);
- }
- }
- equals(ownKeys.length, __, 'how many elements are in the ownKeys array?');
- ok(ownKeys.equalTo([__, __]), 'what are the own properties of the array?');
-});
-
-test("constructor property", function () {
- var a = new A();
- var b = new B();
- equals(typeof(a.constructor), __, "what is the type of a's constructor?");
- equals(a.constructor.name, __, "what is the name of a's constructor?");
- equals(b.constructor.name, __, "what is the name of b's constructor?");
-});
-
-test("eval", function() {
- // eval executes a string
- var result = "";
- eval("result = 'apple' + ' ' + 'pie'");
- equals(result, __, 'what is the value of result?');
-});
diff --git a/topics/about_scope.js b/topics/about_scope.js
deleted file mode 100644
index 10278fcf..00000000
--- a/topics/about_scope.js
+++ /dev/null
@@ -1,28 +0,0 @@
-
-module("About Scope (topics/about_scope.js)");
-
-thisIsAGlobalVariable = 77;
-
-test("global variables", function() {
- equals(thisIsAGlobalVariable, __, 'is thisIsAGlobalVariable defined in this scope?');
-});
-
-test("variables declared inside of a function", function() {
- var outerVariable = "outer";
-
- // this is a self-invoking function. Notice that it calls itself at the end ().
- (function() {
- var innerVariable = "inner";
- equals(outerVariable, __, 'is outerVariable defined in this scope?');
- equals(innerVariable, __, 'is innerVariable defined in this scope?');
- })();
-
- equals(outerVariable, __, 'is outerVariable defined in this scope?');
- var isInnerVariableDefined = true;
- try {
- innerVariable
- } catch(e) {
- isInnerVariableDefined = false;
- }
- equals(isInnerVariableDefined, __, 'is innerVariable defined in this scope?');
-});