- Objects Only, No Classes
- Functions are just Values
- The 'this' Keyword
- Classic vs Prototypal Inheritance
- Constructors vs Constructor Functions
- Closures vs Lambdas
- Encapsulation and Modules
- Block Scope and Hoisting
Objects Only - No Classes
Take for example this program, that initializes an empty object and set's two properties:
Functions Are Just Values
Function, it's a simple as that! Take for example:
This creates a function (a value of type
Function) and assigns it to a variable
flyFunction. A new property named
fly is then created in the superhero object, that can be invoked like this:
Function type, but almost. Take for example the
SuperHero class that takes a
This is how to pass
SuperHero a function in Java 7 and 8:
So although a
But if we pass functions around, what happens to the meaning of the
The 'this' Keyword Usage
this is quite surprising compared to the Java world. Let's start with an example:
This program creates an object
superman with two properties: a String
heroName and a
sayHello. Running this program outputs as expected
Hello, I'm Superman.
What if we pass the function around?
By passing around
sayHello, we can easily end up in a context where there is no
Running this snippet would give as output:
Hello, I'm undefined.
this not work anymore?
This is because the variable
failThis belongs to the global scope, which contains no member variable named
heroName. To solve this:
thiskeyword is completely overridable to be anything that we want!
The snippet above would print again
Hello, I'm Superman. This means that the value of
this depends on both the context on which the function is called, and on how the function is called.
Classic vs Prototypal Inheritance
That property is called
__proto__, and the parent object is called the object's prototype, hence the name Prototypal Inheritance.
This snippet will output
Iron Man is copyrighted by Marvel.
As we can see, although the
ironMan object is empty, it's prototype does contain the property
editor, which get's found.
How does this compare with Java inheritance?
Let's now say that the rights for the Avengers where bought by DC Comics:
avengersHero.editor = 'DC Comics';
If we call
ironMan.editor again, we now get
Iron Man is copyrighted by DC Comics. All the existing object instances with the
avengersHero prototype now see
DC Comics without having to be recreated.
This mechanism is very simple and very powerful. Anything that can be done with class inheritance can be done with prototypal inheritance. But what about constructors?
Constructors vs Constructor Functions
Notice the capitalized name, indicating that it's a constructor function. Let's see how it can be used:
This code snippet outputs
Hello, my name is Superman.
You might think that this looks just like Java, and that is exactly the point! What this
new syntax really does is to it creates a new empty object, and then calls the constructor function by forcing
this to be the newly created object.
Why is this syntax not recommended then?
Let's say that we want to specify that all super heroes have a
sayHello method. This could be done by putting the
sayHello function in a common prototype object:
This would output
Hello, my name is Superman.
But the syntax
SuperHero.prototype.sayHello looks anything but Java like! The
new operator mechanism sort of half looks like Java but at the same time is completely different.
Is there a recommended alternative to
new operator altogether and use
Closures vs Lambdas
We can can pass it a fly command like this in Java 8:
The output of this snippet is
Flying to Mars. Notice that the
FlyCommand lambda had to 'remember' the variable
destination, because it needs it for executing the
fly method later.
What is the main difference between Lambdas and Closures?
destination variable must be immutable (or effectively immutable since Java 8).
Modules and Encapsulation
private modifiers, but then again take a look at this:
Here a function
createHero is being defined, which returns an object which has a function
fly function 'remembers'
name when needed.
How do Closures relate to Encapsulation?
createHero function returns, noone else will ever be able to directly access
name, except via
fly. Let's try this out:
The output of this snippet is
SuperMan flying to The Moon. But happens if we try to access
name directly ?
console.log('Hero name = ' + superman.name);
The result is
Hero name = undefined. The function
Block Scope and Hoisting
By looking at this coming from Java, you might expect:
- error at line 3: 'variable i does not exist'
- values 0, 1, 2 are printed
- error at line 9: 'variable i does not exist'
It turns out that only one of these three things is true, and the output is actually this:
counter before declaration = undefined counter = 0 counter = 1 counter = 2 counter after loop = 3
Because there is no block scope, the loop variable i is visible for the whole function. This means:
- line 3 sees the variable declared but not initialized
- line 9 sees i after the loop has terminated
What might be the most puzzling is that line 3 actually sees the variable declared but undefined, instead of throwing
i is not defined.
To prevent surprises caused by hoisting and lack of block scoping, it's a recommended practice to declare variables always at the top of functions.
Some of these features are needed mostly by library developers, and not necessarily for day to day application programming. This is unlike some of their Java counterparts which are needed every day.
So if you are hesitant to give it a try, don't let some of these features prevent you from going further into the language.
If you are interested in Type-Safe Frontend Development
If that is the case, you might want to have a look at our ongoing YouTube course on Angular 2 - Getting Started With Angular 2: