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