Discovering The Most Misunderstood Programming Language. JavaScript

JavaScript is Misunderstood

Javascript is like the bad villain in a movie. It is misunderstood so much no one will take the time to learn it. No one would think it is worth their time to learn javascript. Instead, everyone expects to just copy/past JS and learn it.

Why is JS misunderstood?

  • The inconsistency of the language across different browsers,
  • A very poor name for a language. JS was named to take advantage of Java's popularity. But it has left it
  • No one thinks it is a real programming language and no one takes the time to learn it.

What is great about JS

  • It's dynamically/weekly typed language,
  • Extremely flexible,
  • Functional style of programming, even though it is not truly functional,
  • Prototypal inheritance, unlike class-based inheritance

JS Ground Rules and Examples

Semicolons might be optional, but don't count on it.

Just use semicolons. For example, in the snippet below, when n is less than 5, JS will just assume you would put semicolon right next return. Hence it will return undefined.

var foo = funciton(n) {
    if(n < 5) {
        return 
            n * 2;
    }
    else
        return n;
}

Variable declarations

Variables declared with var are local but without them, it is always global scoping no matter where you are. No block scoping. Example:

var foo = function(n) {
    for(i = 0; i < 10; i++) {
        foo2();
    }
    var local1 = 7;//Local variable
    console.log(local1);
    local2 = 2;//JS assume it is global
}
foo(3);
console.log(local1);//Error because it is local.
var foo2 = function(){
    for(i = 0; i < 10; i++) {//Now since i is declared above without var in it, you are literally screwed here.
    }  
}

Another way to avoid these situations is to use option strict. On top of the avoce code just add

"use strict"
//It will result in an error on the local2 variable declaration because it is not declared with var.

Defining functions

When you define a function, you are declaring a variable, whichever technique you use. There are two and halfway of defining a function and Dr. Venkat highly recommend the first here is why.

var foo = function() {
    console.log('Foo called');
}
foo();
foo = function() {
    console.log('Foo redefined');
}
foo();

The output of this code is what you would expect. The first call of foo results in Foo called and the second results in Foo redefined. However, if we use the declarative function definition like below, we will be surprised.

function foo() {
    console.log('Foo called');
}
foo();
function foo() {
    console.log('Foo redefined');
}
foo();

Now the output of this code is as promised a surprise. In both calls of foo() it results in Foo redefined. Because it's This situation is called 'Hoisting' and if you understand it well use it, otherwise stick with the first definition.

Function Arguments

In JS the number of parameters a function takes is determined by the caller of the function, not the declaration. That means unlike Java, C# or C++; if you call a JS function with more than the declared arguments, it would cordially accept them and does the intended computation.

var max = function(a, b) {
    if (a > b)
        return a;
    return b;
}

console.log(max(2, 1));//2
console.log(max(2, 3));//3
console.log(max(2, 3, 1));//3
console.log(max(2, 3, 7));//3

But what is going on there? It seems to accept every parameter but doesn't seem to even care about the variables other than the first two. That is because JS function can accept any number of parameters but we can either represent them in our declaration like we did up there or use a smart approach like below.

var max = function() {
    //May be check arguments is not empty first
    var large = arguments[0]; //arguments is a JS keyword that returns all the arguments of a function call.
    for(var i = 0; i <= arguments.length; i++) {
        if(large < arguments[i]) 
            large = arguments[i];
    }

    return large;
}

console.log(max(2, 1));//2
console.log(max(2, 3));//3
console.log(max(2, 3, 1));//3
console.log(max(2, 3, 7));//7
console.log(max(2, 3, 7, 10, 1));//10

The this keyword and calling functions using call and apply functions

this is a context variable/object every function carries with it by default and it is useful to associate a function with an instance. As a result, all functions have the this object and you can call it anywhere within a function. Unlike other programming languages, especially OOP languages, in JS functions don't belong to any class. So you can take ownership anytime you want using your object.

Example:

var greet = function(name){
    console.log(this.toUpperCase() + ' ' + name);
}
greet('Joe');//You would expect this to work, but it results in an error.
greet.call('Hello', 'Joe');//This results in HELLO Joe.

So what is the difference between calling a function directly and using the call function? Since functions are just objects in JS you give different content object by calling another function. So the call function takes an n+1 parameters, where n is the parameter of the first function.

Now, what if we want to pass an array of names instead of just 'Joe,. In that case, we use to apply function.

var names = ['Tom', 'Jerry'];
greet.apply('Hello', names);//This results in HELLO Tom and HELLO Jerry.

The first parameter of call and apply are always the context parameter.

Higher-order functions

You can use higher order functions to be effective and efficient. Higher order function is a function that can accept another function as an argument. Higher-order functions make JS well suited for functional programming. Also, JS already comes with a number of higher-order functions that are way efficient to what you would write. Example: When working with an array of elements we can use old school for loop but we can also do stuff like this.

var list = [1, 2, 3, 4, 5, 6];

list.filter(function(e) {return e % 2 == 0; })//To print only the double of the even values
    .map(function(e) { return e * 2; })//To print the double of the values
    .forEach(function(e) {console.log(e) }); //To print each element

Even better, lambda function or arrow function; as of ECMA6 syntax.

var list = [1, 2, 3, 4, 5, 6];

list.filter(e => e % 2 == 0)//To print only the double of the even values
    .map(e => e * 2; })//To print the double of the values
    .forEach(function(e) {console.log(e) }); //To print each element

What to use === or ==

In short, the double js equal == is just messed up. Let's jump street to the examples,

var a = "1";
var b = 1;
var c = "1.0";

console.log(a == b);//Js returns true 
console.log(b == c);//Js returns true
console.log(a == c);//Js returns false. No logic in js? Why?

There is no logic in the above code and the reason is JS double equal doesn't do comparisons. It does a comparison by converting objects. So, don't use double equal anymore! use triple equal instead.

console.log(a === b);//Js returns false 
console.log(b === c);//Js returns false
console.log(a === c);//Js returns false.

Consistent and precise.

Likewise, when doing a not equal use the triple equivalent.

console.log(a !== b);//Js returns true 
console.log(b !== c);//Js returns true
console.log(a !== c);//Js returns false.

Functions are objects with properties

Functions are objects and objects can function as well. Objects are a collection of properties and functions. In JS, you don't need classes to create objects.

Creating objects

var person = {
    firstName: 'Sam',

    lastName: 'Walker',
    age: 2,
    play: function() { console.log('playing...'); }
}

console.log(person.age);
person.play();

The best thing about JS objects is the prototype.

What is Prototype?

Think of Prototype as a backpack every object carries around. So how do we use our backpack?

var worker = {
    work: function(){ console.log('Working...'); }
}
var person = {
    firstName: 'Sam',
    lastName: 'Walker'
}

var use = function(inst) {
    try {
        inst.work();
    } catch(ex) {
        console.log(ex);
    }
}
use(sam);//Error inst.work is not a function
sam.__proto__ = worker;
use(sam);//Working

What this means is by using prototype, we enable every object to have access to every function. This even becomes very convenient for automated testing.

Besides, it enables inheritance. Unlike class-based inheritance, JS prototype enables dynamic and unlimited inheritance.

Creating Classes

var Car = function(year) {
    this.year = year;
    console.log("Car created");
}
var car1 = new Car(2015);
console.log(car1.year);//2015

Car in the above snippet is not a function, it is a class. Technically JavaScript doesn't have classes, yet when we make our function name capital it becomes a constructor of a class.

The new keyword

The new keyword enables prototype inheritance like this.

  1. Memory is allocated for the instance, let's call that inst.
  2. Car.call(inst, 2015);
  3. `inst.proto = Car.prototype;

Summary

JS is a very powerful language if only you use it well. Especially, the context object, the apply and call function are handy if you write complex objects. And finally, the prototype inheritance give JS super program abilities.

Subscribe for coding videos

Keep growing professionally with just three curated videos weekly.

We hate spam as much as you do.