Grok.JavaScript()

Intro

Javascript is one of the world’s most popular programming languages. In the early days of the web, the language was used to create simple scripts that did handy things, like check to make sure you filled out all the "required" fields on a form. As Internet connections got faster and browsers got more sophisticated, Javascript evolved into a tool for building all sorts of complex web-based apps. Some rival desktop apps in size / functionality.

Javascript is a high-level, dynamic, untyped, and interpreted programming language. JavaScript can be an eloquent language if written the right way, but in the hand’s of a bad programmer, JavaScript can be ugly and error prone. This tutorial will not only teach you the syntax and semantics of the language, but also instill proper coding principles.

This tutorial assumes that you have prior object oriented programming experience in a language such as Java, C++, etc.

Variables, the core of all programming languages, are where we will begin. Traditionally the programmer must declare the type of variable, but in JavaScript this is not the case. JavaScript is a weakly typed language; i.e. the type is inferred. It is also dynamically typed, so a variable’s type can change.

var juan = 1;
juan = "one";
juan = [];
juan = { };
juan = true;

These are all legal expressions. In JavaScript you can change a variables type on the fly no questions asked. This is obviously to be avoided, as it leaves future code maintainers scratching their heads wondering what you were thinking.

The basic types are as follows:

  • Number
  • String
  • Boolean
  • Function
  • Object
  • Symbol (new in ES6)
But some special objects are included too. Array, Data, and RegExp are kinds of objects that do what you'd expect. Also, technically speaking, Functions are just a special kind of Object. And I can't leave out null and undefined, whose difference is spelled out in the example code. So the types you start with looks more like this:
  • Number
  • String
  • Boolean
  • Symbol (new in ES6)
  • Object
    • Function
    • Array
    • Date
    • RegExp
  • null
  • undefined

In JavaScript, functions are objects, meaning they can have properties and methods just like any other object. What distinguishes them from other objects is that functions can be called. Functions can get pretty tricky. For now we will go over the fundamentals and cover more advanced topics later.

Functions can be declared one of two ways

var doSomething = function() {
  . . . 
}

/* is the same as */

function doSomething() {
  . . . 
}

The difference being is that functions declared the second way is "hoisted", meaning, the Javascript engine reads all these declarations first before executing any of the rest of the code. The declaration statement stands alone, and cannot be combined with other expressions. Play with the first example in the code to gain understanding.

Think of an object as a collection of things. For example, imagine you have a ship. That ship is your object and contains a collection of other things. We’ll call these "properties". The ship’s properties might contain the year it was built, the name of the ships captain, the number of passengers aboard, etc. Functions and other objects and be properties as well.

Taken from the MDN:

JavaScript is designed on a simple object-based paradigm. An object is a collection of properties, and a property is an association between a name and a value. A property's value can be a function, in which case the property is known as a method. In addition to objects that are predefined in the browser, you can define your own objects.

You can define an object using literal syntax like this:

var titanic = {
  maidenVoyage: 1912,
  numberOfPassengers: 1317,
  captain: {
    name: "Edward John Smith"
  },
  sendSOS: function() {
    console.log("SAVE OUR SHIP")
  }
}

You can access those properties like this:

titanic.maidenVoyage // 1912
titanic["numberOfPassengers"] // 1317

This may look weird to you, but you can think of JavaScript objects as a hash map with the property names being the keys.

Arrays are a little different then they are in Java and C++. Arrays in JavaScript can grow and shrink and there are many helper methods provided for you. Take a look at the following code snippet for a quick example.

var bag = ["cola", "sandwich", "cake"] 

Don’t forget, JavaScript is weakly typed, so the following is legal code.

var trash = ["garbage", 10, true, { name: "Jack", hours: 24 } ] 

The forEach method is extremely helpful for iterating through an array.

bag.forEach(function(item){
    console.log(("i love " + item).toUpperCase());
});

or even

function yell(item) {
    console.log(("i love " + item).toUpperCase());

}

bag.forEach(yell);

Things can get pretty tricky in JavaScript, so we are going to go over some more advanced features in depth. Carefully go throguh the code in this chapter, and make sure that you have a full understanding of what is going on.

Equality

The == operator will compare for equality, but will apply any necessary type conversions first.

The === operator will not do any conversions, and returns false if the two operands are not the same type.

So if a string and a number are being compared using ==, the string will be converted to a number and then compared. Check out the following code:

if (4 == "4") {
  var sameAs = (4 === parseInt("4"));
  console.log(sameAs);
}

There are many different rules for comparing different types and they are laid out in the specification. Unless you know exactly how you are using the ==, always use the === instead

Functions

It is possible to immediately invoke a function. The function name is declared within its own scope, so it cannot be called later in the program.

(function (){
  console.log("first");
}());

console.log("second");

Immediatlely invoked functions are important because they do not pollute the global namespace. Many librarys use this technique so that their code does not cause global variable conflicts.

You can assign the result to a variable, but still do not expect to call the function later.

var result = function add(a, b){
  return a + b;
}(3, 4);

console.log(result); // 7
add();  // Error

If you recall in some of the previous chapters, we passed in already defined functions as parameters. Well, you can actually define the function as an argument and use it on the fly. You'll see this come up often in other Javascript code.

var nums = [1, 2, 3];
function square(val) {
  return val * val;
}

/* old way */
var squared1 = nums.map(square);

/* function declared inline */
var squared2 = nums.map(function(n) {
  return n * n;
});

console.log(squared1.toString());
console.log(squared1.toString());

Closures

Closures are a complicated beast to explain, so I am going to the experts and stackoverflow handle this one. This post does a fantastic job of explaining closures. The code in that post is the same code that you can play with here.

Below is another example covering closures in a basic sense.

function counter() {
    var count = 0;
    return function() {
        console.log(count++);
    }
}
var juan = {}, tew = {};
juan.count = counter();
tew.count = counter();
juan.count(); // "0"
juan.count(); // "1"
tew.count(); // "0"
tew.count(); // "1"

ECMAScript (ES) is the standard that JavaScript is based on. JavaScript starts out with ES and provides additional features. ES is important to the history of JavaScript and you can read more about it on its wikipedia page. The latest release of ES is ES6. We will highlight the important new features.

let & const

We have already talked about let so we will focus on const. const allows you to declare variables immutable i.e. a constant.

const max_width = 10;
max_width       = 20;    // Error

Arrow function

Old

doThing(true, function(d) {
    . . . 
});

New

doThing(true, d => {
    . . .                             
});
                            

This is arguably the most important change introduced in ES6. The arrow function => allows you to retain scope when working inside a function. Normally the this keyword refers to the function it is in. However, when using the arrow function, the this keyword refers to object that owns the function. Basically, when using the arrow function, the this keyword operates like you would expect it to in OOD.

Take a look at the example code

Parameters

ES6 has introduced additional features to function parameters

You can now set default parameter values

function f (x, y = 7, z = 42) {
    return x + y + z
}
f(1) === 50

You can aggregate remaining arguments into an array

function f (x, y, ...a) {
    return (x + y) * a.length
}
f(1, 2, "hello", true, 7) === 9

Finally, when specifying the ... in the actualy call, you can "spread" an array into multiple parameters

function f(x, y, z) {
  return x + y + z;
}
// Pass each elem of array as argument
f(...[1,2,3]) == 6