JavaScript - Most Important Features Pt. 2

JavaSctipt language interesting properties from the perspective of a C/C++ programmer - continued.

Displaying help

To show help in the terminal, type .help. To exit, type .exit (notice the dot as the "escape character" for the commands in node CLI).

Loading and saving sessions

Node gives you the ability to restore your command session. To do this, follow the instructions below.

To load code from a file into the CLI, use .load <filename>. The filename should contain the extension as well - contrary to the customs of the require(); command which looks for the appropriate file type by itself. This necessity is proven by the picture below.

In the picture we see that the .load command did not work when file extension was omitted.

You can also save your session. To save it, type .save <filename>. The file will contain the commands you issued

Let vs var

If you you use let instead of var to declare a variable, the variable will belong only to the current code block, be it a while loop or an if conditional statement.

Strict Mode

Strict mode should be used whenever possible - it enables the compiler to optimize some parts of the source code.

One thing Strict Mode does is disallowing implicit auto-global variable declaration from omission of the var/let statement.

Functions as values

A function itself can be a value that is assigned to variables or passed to or returned from other functions!

// An anonymous-function variable:
var foo = function() {

};
// A named-function variable:
var x = function bar() {

};

Named function expressions are preferred, but anonymous function expressions are still extremely common.

Then the functions are called like this:

> foo();
undefined
> x();
ReferenceError: x is not defined
> x = function calc() {
... return 1;
... }
[Function: calc]
> x
[Function: calc]
> x();
1
> 

Immediately Invoked Function Expressions

The IIFEs look as follows:

(function IIFE() { .. })();

The ending bracket () is exactly what runs the function right after it has been defined inside the previous bracket.

> var x = (function IIFE() {
... return 42;
... })();
undefined
> x;
42

Closure

Closure is said to be one of the most important, and often least understood, concepts in JavaScript.

You can think of a closure as a way to "remember" and continue to access a function's scope (its variables) even once the function has finished running.

I can even print out a previously defined function:

> function makeAdder(x) {
... // parameter 'x' is an inner variable
... 
... function add(y) {
... return y + x;
... };
... 
... return add;
... };
undefined
> makeAdder.toString()
'function makeAdder(x) {\n// parameter \'x\' is an inner variable\n\nfunction add(y) {\nreturn y + x;\n};\n\nreturn add;\n}'
> plusTen(13);
23
> plusTen(999999999999999999999999999999999999999999999999);
1e+48
> plusTen(0x00);
10
> plusTen(0x10);
26
> plusTen(00000010);
18 

Why 18? In decimal, this would be 10 + 10 = 20, in binary, would be 2 + 10 = 12.

Anyway, closure, so the author says, is one of the most powerful and useful technique in all of programming and it is worth spending a significant bit of time over. The "Modules" section to come will be one of the ways of staying with closures a little bit longer.

Modules

Modules let us define private implementation details (variables, functions) that are hidden from the outside world, as well as a public API that is accessible from the outside.

Consider the following code:

> function User() {
... var username, password;
... function doLogin(user, pw) {
..... username = user;
..... password = pw;
..... }
... 
... var publicAPI = {
... login: doLogin
... };
... 
... return publicAPI;
... }
undefined
> var fred = User();
undefined
> fred.login("fred", "12Battery34!");
undefined
> 

Executing User() creates an instance of the User module - a whole new scope is created, and thus a whole new copy of each of these inner variables/vundtions. We assign this instance to fred. If we run User() again, we get a new instance, entirely separate from fred.

The inner doLogin() function has a closure over username and password variables. It means that it will retain access to them even when the User() function finishes running.

Trying: Can I access username after the function is terminated?

Loading modules

To test new code efficiently, you can use the module mechanism. Create a module and use something like fs = require('fs'); to load the module under the exemplary name fs.

Modules are looked for in the original node module directory, as well as in the node_modules directory, or matched against .js, .json and .node extensions if module name is prepended with ./, / or ../ (maybe not exclusively).

To turn a file into a module, you can use the export clause. It allows you to export your own objects and functions.

To be continued

You now learned to handle the Node interactive command line interface. Nevertheless, JavaScript has more to interest you.


Photo by Josue Valencia / Unsplash