Javascript for dummies
Oh I remember back in the day when times were so much simpler and all I used was Visual Studio to develop puny Web based tic-tac-toe games in VB and Javascript was just a tool that allowed me to change some colours. What a blast.
Whoever reads this first paragraph will think I'm a 50-year-old nerdie. I'm just 25, for that matter.
But what's most important is: things have changed. Nowadays I still work in Visual Studio, but with C#, and not limited to this, I also work with Java, PHP, I do have a much more comprehensive knowledge on SQL queries and even no-SQL databases. But one thing hasn't changed (and I totally doubt it will, ever), which is the presence of Javascript in my life. This one language has been calling my attention so savagely that I couldn't help but surrender to its gracefulness. And it seems like people all around the world have been discovering its marvels as well.
These are extracts from Stackoverflow's User Survey results for 2013 and 2017 for most popular language in the community. We can notice that in just four years, not only has Javascript increased its popularity to become the most used language (by far) but also the variety of languages more than doubled. This thanks to the open-source community, which has been developing new libraries and frameworks every other heartbeat and the increasing interest for new languages and different paradigms among developers.
Now, returning to Javascript. Its syntax is somewhat similar to its (distant) cousin Java, but the differences are so that it makes me cringe when people come to me asking if Javascript and Java are the same. Yeah, they still do it. But, for the sake of all Javascript developers (and also Java developers) and the fact that this article is already getting monstrously big, I am going to run through some features that makes Javascript the awesome language it is (nothing against Java, btw).
Dynamic
Java is known as a very strict language, strongly typed and full of rules, just to let the old imperative paradigm behind and praise the Object Oriented paradigm.
But in Javascript everything is an object. It doesn't mean that it is not typed, but everything in the language inherits from the same principle, and can be attributed to variables. Strings, numbers, arrays and, yes, functions (!!!) can all be treated as objects, which allows Javascript to be a flexible and dynamic language, letting the developer to choose which paradigm they prefer, either imperative, object oriented or functional. Talking 'bout that...
Functional programming
Since the 50s, Lisp has been trying to settle functional programming to the mainstream, but not everyone was really interested. With Javascript, as functions can be treated as objects, be attributed to variables and be passed as parameters in another function, functional programming became much more natural, using tail calls, context bindings and, of course, closures, which by the way brings me to my next topic.
Closures
Closures are one of the most useful features in Javascript. It allows you to create mini environmental scopes and transport it through variables. Sounds familiar? Yes, this is the way Javascript dealt with object orientation before ECMAScript 6. It works by hosting functions inside other function (high-order functions) and this parent function would work as a constructor for the object, and all the variables inside it automatically turn into stateful properties. As Javascript doesn't have built-in encapsulation, developers usually leverage closures to make attributes "private", returning a JSON object with getters and setters, just like this:
function Closure(){
var name = "João"
var age = 25
return {
getAge: function(){ return age },
getName: function(){ return name },
setName: function(newName){ name = newName }
}
}
var closure = new Closure()
closure.getName() //outputs "João"
closure.setName("test")
closure.getName() //outputs "test"
closure.age //outputs undefined
null or undefined?
Javascript has two forms of dealing with values that represent nothing. "undefined" is a value that Javascript itself attributes to any variable which hasn't been defined yet (thus the name). "null" is an object that represents nothing and is not used by the Javascript engine at all, it is all on the developer to set variables to null. So it's very useful as to know which variables were created by the engine or by human code. Superficially they work the same, but behind the curtains they are very different...
Type coercion
Besides the canonical boolean operators, Javascript introduced a new one, "===" (and its counterpart, "!==") to deal with its dynamic nature. The issue was that, as it is a dynamic language, a mechanism was created so that the code wouldn't crash when comparing two values of different types. This mechanism is called type coercion and it works like this:
console.log(5 == "5") //outputs "true
Javascript tries to convert one of the values to the same type of the other, so that they can be compared. But what happens if I type this:
console.log(5 === "5")
It will output false, because the "===" operator is immune to type coercion, and can argue that, even though their absolute values if converted are equal, their types are different, so they must be different. Same thing happens to null and undefined:
console.log(null == undefined) //outputs "true
console.log(null === undefined) //outputs "false
No code crash
...at least with basic number operations, yes, Javascript does not crash. One example is in the above topic, type coercion. Also, in illegal arithmetic operations, such as square root of negative numbers or in illegal string parsing (parsing a letter into a number, for example), Javascript will return the value NaN, which means "Not a Number" and belongs to the Number type (???). NaN is also the only value in Javascript that is not equal to itself (non-reflexive).
console.log(NaN == NaN) //outputs false
console.log(NaN === NaN) //outputs "false
console.log(isNaN(NaN)) //outputs "true
On the other hand, if we try to calculate a number that exceeds the 64-bit floating point limit (good luck with that), we get Infinity (either positive or negative).
console.log(2E+10308) //outputs Infinity
console.log(-2E+10308) //outputs -Infinity
Infinity is also a Number, but it cannot be subtracted from itself.
typeof Infinity //outputs "number"
console.log(Infinity - Infinity) //outputs NaN
console.log(Infinity / Infinity) //outputs NaN
console.log(Infinity + Infinity) //outputs Infinity
console.log(Infinity * Infinity) //outputs Infinity
Reading this topic, if you are well-versed in arithmetics, you could start to think what the illegal operation "divide by 0" would output. Many would think that it would output NaN, because it makes sense, right?
console.log(3 / 0) //outputs Infinity (...?)
Yeah, it outputs Infinity, because of reasons.
No semicolon? No problem!
Javascript mostly eliminates one of Java developers' most intrinsic, cruel and loathsome compiling nightmares, the lack of end-of-line semicolon. If you notice in the code examples in this article I haven't used the semicolon once. Javascript never demanded semicolons, and it's totally on the developer to use them or not.
console.log("Hello world") //valid!
console.log("Hello world"); //still valid!
console.log("Hello world");;;;;;;;;;;;;;;;;;;;; //valid as well!!!!!
Although, there is one caveat in which you will need to use semicolons, which is before IIFEs:
var test = true
;(function(){
return test
})()
This is because the interpreter assumes that parentheses are just to set parameters for functions, and it will try to parse the previous command (in this case, "true") as a function. So to avoid broken references, whenever you use an IIFE, put a semicolon at the start of it, no fear. But...
IIFEs
Oh right, I was going to ask this. An IIFE is an Immediately Invoked Function Expression. A function expression is an object representing a function that can be attributed to variables and passed as parameter in another function. In order to immediately invoke it, it need to be wrapped in parentheses and then call its parameters, like so:
;(function(){
return "Hello World"
})() //even though there are no parameters we need to make parentheses call!
//or
;(function(){
return "Hello World"
}())
This one little feature allows you to create separate scopes that cannot be affected from outside, unless you provide it parameters. IIFEs and Closures generally give hands to simulate encapsulation in Javascript, thus making the language way safer.
Context binding
In Javascript, if you run functions outside a Closure and you use the keyword this, you will probably be referencing the Window object (in a Browser). If you wish that, e.g. your IIFE has a different context so that you can reference this without interacting with the global Window object, you just need to bind it to any other object, like so:
var divisibleBy = function(i){
var divisible = []
for(n in this){
if(this[n] % i === 0) divisible.push(this[n])
}
return divisible
}
var divisibleBy2 = divisibleBy.bind([1,2,3,4,5])(2)
This way, divisibleBy2 will receive an array containing [2, 4], because its context was the array [1, 2, 3, 4, 5]. This is a silly example, but this has a lot of potential in the language.
...
Wow, that was a lot of content right there. But there is much more on Javascript than this, and you can see it all in https://developer.mozilla.org/docs/Web/JavaScript, the Mozilla page for Javascript how-tos and novelties, which I used as reference for most of this article. So there you go, use Javascript, I promise, it's good.