Javascript : Test-Driven Learning
This project is aimed to help the user further study Javascript with a test-driven approach. Each unit contains an annotated tutorial and a platform where you can test your understanding of the topic.
Topics
- Arrays
- Bad Practices and Solutions
- Booleans
- Built-in Functions
- Closure
- Comparisons
- Conditionals
- Exceptions
- Falsey Values
- Functional Javascript (new)
- Function Expressions
- Function Expressions as Parameters
- Functions
- General Performance
- Hoisting
- Logical Assignment
- Loops
- Namespaces
- Numbers
- Object Prototype
- Objects
- Objects Functionality
- Prototypes
- Strings
- Switch Block
- Ternary Conditionals
- Truthy Values
- Variables
Tools
Arrays
/* An array is a data structure with automatically indexed positions*/
it('Arrays can be accessed by indices', function () {
//The brackets indicate to the compiler to make an array and to fill it with
//the comma-separated values between the brackets
var arrayOfStrings = [ "StringZero" , "StringOne" , "StringTwo"];
//We can access any location of the zero-based array
expect(arrayOfStrings[1]).toBe("StringOne");
});
it('You can reference and change specific cells with indices', function () {
var arrayOfStrings = [ "StringOne" , "StringOne" , "StringTwo"];
arrayOfStrings[0] = "StringZero"; //You can change the value contained at any index
expect(arrayOfStrings[0]).toBe("StringZero");
});
Functions
/*Functions take some input, then execute a series of statements using the input, and outputs a result*/
it('functions help write reusable code', function () {
expect(addNumbers(1, 2)).toBe(3);
expect(addNumbers(2, 3)).toBe(5);
expect(addNumbers(1 + 1, 2 + 1)).toBe(5);//Parameters can also be expressions, which the function will resolve before starting
var numberOne = 2;
var numberTwo = 3;
expect(addNumbers(numberOne, numberTwo)).toBe(5);//Parameters can also be variables
});
// function keyword tells the compiler that you are defining a function
function addNumbers(numberOne, numberTwo) { //The function's name follows the 'function' keyword and should indicate the function's purpose
//Parameters are passed in a set of parentheses before the first curly brace
return numberOne + numberTwo;
//The return keyword works as a terminating statement and exits the function returning the value in front of it
} //The statements that will be executed should be enclosed in curly braces.
Numbers
it('JavaScript uses binary floating point values to handle all of its decimal based operations', function () {
expect(0.1 + 0.2).toBe(0.30000000000000004);
});
it('You can use the toFixed() method to select the amount of decimal places to display', function () {
expect((0.1 + 0.2).toFixed(1)).toBe('0.3');
});
it('toFixed() method will round to the last indicated position', function () {
//0.18 + 0.28 = 0.46
expect((0.18 + 0.28).toFixed(1)).toBe('0.5');
});
it('parseFloat() turns strings with decimals into numbers', function () {
expect(parseFloat((0.18 + 0.28).toFixed(1))).toBe(0.5);
});
it('parseInt() looks for the first available integer at the front of a string', function () {
expect(parseInt("55")).toBe(55);
expect(parseInt("55 is a great number")).toBe(55);
});
it('if parseInt() does not find an acceptable value at the beginning of a string, it will return a NaN', function () {
expect(parseInt("A great number, 55")).toBeNaN();
});
it('parseInt() will trim off any decimals that may exist, without rounding', function () {
expect(parseInt("5.78")).toBe(5);
});
it('parseInt() will accept octal,hexadecimal and decimal values potentially creating undesired results', function () {
//"021" is read as an octal value(base 8) and converts it to decimal
expect(parseInt("021")).toBe(17);//This is fixed on ECMAScript5
});
it('you can use a radix value to ensure correct parsing', function () {
//parseInt will accept any radix value from 2-36 for selecting the Base for the result
expect(parseInt("021", 10)).toBe(21);
});
Anonymous Closures
//When you create NAMESPACES, the program may still execute its private methods and variables
//It is good practice to use private methods to safely modify private data
//Anonymous Closures allow you to define public and private variables
it('Closures will allow you to make private variables and properties', function () {
//You can achieve this by surrounding the entire set of properties and values in an immediately
//invoked function expression
//The local values and methods will be "closed" into the namespace
var NAMESPACE = (function () {
var privateArray = [1, 2, 3];
var privateVariable = 9;
//In order to make public properties, you can return an object
return {
//Since the function expression is invoked, this returned object will be handled immediately
// to the NAMESPACE variable and become a namespace
publicArray: function () {
return [4, 5, 6];
},
publicVariable: 10 + privateVariable
};
})();//These parentheses indicate that the function expression should be immediately executed
//Since privateArray and privateVariable are private, we expect them to be undefined
expect(NAMESPACE.privateArray).toBeUndefined();
expect(NAMESPACE.privateVariable).toBeUndefined();
expect(NAMESPACE.publicArray()).toEqual([4, 5, 6]);
expect(NAMESPACE.publicVariable).toBe(19);
});
Prototypes
/*Class : Set of Objects that inherit properties from the same prototype*/
it('You can create Constructors that allow to set up inheritance while also assigning specific property values', function () {
//Capitalizing this function's name distinguishes it as a maker of an entire "Class" of objects
function Person (firstName, lastName ,age){
//'this' keyword inside a constructor will automatically refer to the new instance of the class that is being made
this.firstName = firstName;
this.lastName = lastName;
this.age = age;
}
//'new' keyword produces a new Object of the specified class
var martinPerson = new Person("Martin", "Chavez", 27);
expect(martinPerson.firstName).toBe("Martin");
expect(martinPerson.lastName).toBe("Chavez");
expect(martinPerson.age).toBe(27);
});
it('You can assign a prototype to a constructor', function () {
function Person (firstName, lastName ,age){
this.firstName = firstName;
this.lastName = lastName;
this.age = age;
}
//Setting a constructor prototype property allows the instances to access these properties
Person.prototype = {
address: "House 123"
};
var martinPerson = new Person("Martin", "Chavez", 27); //There is no need to define the address for each person
expect(martinPerson.address).toBe("House 123");
});
it('You can modify the message functions in a prototype to use the data values in the calling instance', function () {
function Person (firstName, lastName){
this.firstName = firstName;
this.lastName = lastName;
}
Person.prototype = {
//'this' keyword searches for the particular Object(Person) that called the inherited function and retrieves the data from it
fullName: function() { return(this.firstName + " " + this.lastName); }
};
var martinPerson = new Person("Martin", "Chavez");
expect(martinPerson.fullName()).toBe("Martin Chavez");
});
it('You can use prototype chaining to reuse functionality', function () {
function Person (firstName, lastName){
this.firstName = firstName;
this.lastName = lastName;
this.blackHair = true;
}
function Baby(firstName, lastName){
//You can call the Person constructor within the Baby constructor
Person.call(this,firstName, lastName);
// We need to add a reference to this Object constructor, otherwise it will use the Person constructor
this.constructor = Baby;
}
// By setting a parent object as a constructors prototype, objects build with that construct gain access to
// all the methods on that object, including the methods on its constructor prototype.
Baby.prototype = new Person();
// You can also add specific methods to this prototype
Baby.prototype.cry = function(){
this.isCrying = true;
};
var baby = new Baby("Martin", "Chavez");
baby.cry();
// Property from the Baby object
expect(baby.isCrying).toBeTruthy();
expect(baby.firstName).toBe("Martin");
expect(baby.lastName).toBe("Chavez");
expect(baby.constructor).toBe(Baby);
// Property from the Person object
expect(baby.blackHair).toBe(true);
});
Install (Works on any platform)
npm install --global npm@latest (if you don't have it already)
npm install --global yo bower grunt-cli
cd LearnJavascript
npm install
bower install
Run the Tests
grunt test