Javascript : Test-Driven Learning
JavaScript
Latest commit f69c47a Oct 30, 2016 @MartinChavez committed on GitHub Add MIT license

README.md

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

Contact

Continue Learning