The Ecma Natives Learning JS like a boss

Lab 1: The basics of Awesome!

Let’s rub those hands together, after last weeks introduction and installation it’s about time we got real!

In this lab we’re going to look at some basic constructions of the JavaScript Language. We’ll dive a bit into the different object types available in the language, some conditional stuff and functions.

You’ll notice that we’re covering a lot of ground today. I understand it’s a bit much, but try to work through it. We need the stuff we learn here to do the rest of the labs later. Next week is going to be a bit easier. I promise ;)

Lets start this course by making sure we got a nice editor in place that helps us write code a bit. During this course I’ll mostly look at an editor called Atom, as it’s easiest to setup and tool.

If you ended last weeks course on an older machine or if you are dealing with a slow VirtualBox, then Atom might be a bit to “heavy” to run on your machine. In that case its better to use “Sublime 3”

If you like to use Sublime instead, follow these instructions for the install.

If you like to use NeoVim instead, Check this post in a few days. I’m writing a mini-guide for it now.

Whenever I prefix a command with $ You should run the command (excluding the $) in your terminal. Whenever I prefix with >, you should execute the command in a NodeJS REPL. If something goes wrong, open an issue on Github and mention the line in the markdown source of this file where things started to go wrong. You can find the source of this page here

Installing Atom.io

Atom is an editor running on JavaScript. Jep, the core of the editor is actually running on the language we’re learning! It can act like a program through the help of a toolkit called “Electron”. Atom was made by the folks that also made GitHub!

boring

I am boring you sorry. Let’s download and install Atom.

OSX & Windows

First we need some node stuff. Let’s install and set up them:

npm install -g eslint
echo '{ "rules": {} }' > ~/.eslintrc

On OSX we need to download and install Atom from their site. Go to the atom site and download Atom for your OS. When that’s done install it and try to open it.

Ubuntu (and VirtualBox)

Installing on Ubuntu will be done through the Ubuntu App-get store. The only problem is that the normal store doesn’t have Atom. So we’re going to add an extra app-source (from which the store can find & download apps) to our apt-get.

$ sudo apt-get -y install wget
$ wget -qO - https://packagecloud.io/AtomEditor/atom/gpgkey | sudo apt-key add -
$ sudo sh -c 'echo "deb [arch=amd64] https://packagecloud.io/AtomEditor/atom/any/ any main" > /etc/apt/sources.list.d/atom.list'

With the new “source” in our app store we can now update the list (to get the latest shopping-lists of apps that can be installed) and install Atom.

$ sudo apt-get update
$ sudo apt-get -y install atom

That’s done!

OSX, windows and Ubuntu

With Atom installed, we got the editor working! Let’s open it up and prepare the rest.

First let’s go into preferences. Once in preferences we’ll go to the install section.

preferences

We’ll install the following packages:

Emmet will auto-complete some nifty things, Linter and linter-eslint will work like spelling and grammar checks, but they will grammar and spell-check your code!

Within settings go to “packages” and hit settings on “linter-eslint”:

settings

Within those settings scroll down until you locate “Global eslint” Follow the instructions by going to a terminal and typing

$ npm get prefix

It should return a path for you. Paste that path into atom (like I did)

prefix

Then copy the first bit (like I did) of that path up until your user-name.
Paste it into the .eslintrc path field and write .eslintrc after it.

While you are in settings you can also change themes in the settings here! My faves are One Dark (which is the default), “atom-material-ui” and “gruvbox-dark-ui”. Knock yourself out!

Let’s REPL

It’s always good to take a peek at the different type of objects we can use. It’s kinda like checking what kind of hammers, saws and screw-drivers you have in your toolbox.

Open a new terminal screen and execute the command below to pop into a NodeJS REPL shell.

$ node

We’ll type some fun commands to get started.

> "hello  World!"
'hello world'

> typeof "hello world!"
'string'

That’s kinda funny isn’t it? When NodeJS sees a boring string (strings without special bits and bops) it will actually prefer you to put them between single quotes. Let’s keep that in mind for the future.

Lets try some other basic types:

> typeof true
'boolean'

> typeof false
'boolean'

> typeof 1
'number'

> typeof 1.1
'number'

> typeof [1, 2]
'object'

> typeof {}
'object'

> typeof function() {}
'function'

> typeof class Testing {}
'function'

Okay, some weird things are happening here.

It’s good to remember that arrays are index-based, this means that the first item in an array is actually the 0th item. Let’s test that.

> ['first', 'second'][0]
'first'
> ['first', 'second'][1]
'second'
> ['first', 'second'].length
2

So we have object 0 and object 1, but the list has a length of 2 items.

wat

Sure, lets look at objects then!

> let thing = { hello: 'world', someNumber: 42 }
undefined
> thing
{ hello: 'world', someNumber: 42 }
> thing.hello
'world'
> thing.someNumber
42

Cool, so we can store bits and pieces of information in objects! Unlike mutable languages you can actually overwrite some things. Let’s take that object from earlier and change something

> thing.hello = 'world!'
'world'
> thing
{ hello: 'world!', someNumber: 42 }

That’s a bit creepy huh? One part of your code can actually change something that was created earlier. It’s fine to do those kind of things, but you need to make sure you name your functions and code in such a way, that it’s easy to understand why and where the “state” of objects are changed.

Chaning
changing values, while they run somewhere else be like.

Did you see me putting a whitespace between { and hello:?
It’s good to put a bit of breathing space between things here and there!

Now without you actually noticing it, we used another piece of special code above. Did you see the let I used there?
When you define a variable name for the first time, you need to prefix it with either let or const. Back in the days of ECMA 3 we only had var (you shouldn’t use that anymore). But let and const are much better.

Let’s experiment with them:

> let foo = 'test 1'
undefined
> foo
'test 1'
> foo = 'test 2'
'test 2'
> foo
'test 2'

> const bar = 'test 1'
undefined
> bar
'test 1'
> bar = 'test 2'
Thrown:
TypeError: Assignment to constant variable.

AHA!!! So when you define a variable with let, you are allowed to “re-assign” it with an entirely different value later, but when you use const you can’t.
That’s handy when you don’t want variables that shouldn’t change to change.

If, else, else if

Like pretty much any other language JavaScript supports conditions. Let’s try some:

> if ('hello' === 'hello')  { console.log('HELLO!' }
HELLO!

> if ( 1 === 2 ) { 'possible!' } else { 'impossible!' }
impossible!

> if ( '1' === 1 ) { 'possible!' } else if (1 === 1) { 'impossible!' }
impossible!

> if ( '1' == 1 ) { 'same content, different types, but it works!' }
same content, different types, but it works!

> if ( !false )  { 'false with a ! is false upside down and thus true' }
false with a ! is false upside down and thus true

> if ( 10 <= 100 ) { '10 is less than or equal to 100' }
10 is less than or equal to 100

> if ( 'something' ) { "anything that isn't false or undefined is actually 'truthy'" }
anything that isn't false or undefined is actually 'truthy'

So these are the different If statements you can use. Do you see the important difference between === and ==?

Generally we never really use ==.

An if statement will resolve “truthy” when it receives true or anything that isn’t false, null or undefined. So you don’t need to try to always get a true.

So far you’ve seen some if else and if else. But there’s an extra one.
The Conditional (ternary) operator. It looks like this:

condition ? 'when truthy' : 'when falsy';

It works like this:

> let tester = 'hello';
> tester ? tester : 'no tester';
'hello'

We need to go deeper! Let’s do functions

Okay, so we got a basic idea of JavaScript’s Types now. There are a few more, but we won’t cover them today.

Let’s see if we can execute some functions, write some callbacks and create some classes. It’s pretty bad to do that in a REPL however so let’s start using that editor of ours!

Let’s exit the REPL (you can also hit ctrl + c twice).

> .exit

Now it would be handy to have a folder reserved to our JavaScript stuff. Let’s go to the home-folder, create a dev folder and put a folder in that called ecma-natives with a lab-1 folder inside. In that folder we’ll put a new file called functions.js

$ cd ~
$ mkdir -p dev/ecma-natives/lab-1/
$ cd dev/ecma-natives/lab-1/
$ touch functions.js

Cool. Before we continue let’s start some version control. In this lab we’re going to create some functions and play with them. It’d be nice if you could scroll back in time later to see the different function options we went through.

$ git init
$ git add .
$ git commit -m "initial commit"

If this is the first time you do git stuff on your computer, you might need to set your username and email. Just follow the instructions in the error that was raised. (it will say something like git config --global user.name). Make sure to fill in your real name and a valid email address. The combo will be your copyright and proof of ownership of the code you write in the future.

Cool, our code is safe! Let’s open the current folder in atom (or sublime). Don’t forget the dot in the end of the command. A . means “do something with the current directory”

$ atom .

Atom

Sweet! Now let’s open our functions.js from the left sidebar in Atom. We’ll start with an easy function.

function hello() {
  console.log('world!');
}

Now if we save this file and execute it from the console, it’s not going to do much. It looks like that function isn’t running at all!

$ node functions.js

We have just defined our function, but we’ll still need to call it somewhere. Let’s add an extra line to our code then

function hello() {
  console.log('world!');
}

hello();

Save it and execute it!

$ node functions.js
world!

Sweet!, what would happen if we didn’t actually add those () on our function call?

function hello() {
  console.log('world!');
}

hello;
$ node functions.js

Ah, so when we pass around a function and don’t add the () yet, the function won’t actually run yet. That’s good to know.

Let’s play with arguments next

function hello(name) {
  console.log(`Hello ${name}`);
}

hello('Peter');
$ node functions.js
Hello Peter

So an argument is parsed between the (), like in pretty much any programming language you’ve used so far. What’s going on with Hello ${ name }?

Up till ECMAScript 3 we’d use constructions like this to add 2 strings to each other:

'hello ' + name;

With ECMAScript 2015 we got the ability to do these kind of things using so called [template literals][template literals]. A template literal consists out of two important bits:

Template literals aren’t supported by Internet Explorer at all, so you’ll need to transpile this bit if you ever use it out in the wild. But all of that’s is for later concern.

Let’s do two more things before we wrap it up for this week:

Like in many languages, JavaScript supports the use of default values in function calls. It works a bit like this:

function hello(name, country = 'Ghana') {
  console.log(`Hello ${name} from ${country}`);
}

hello('peter');

When you run this you’ll see:

$ node functions.js
Hello Peter from Ghana

Neat! It’s important to remember that optional arguments go last. If you are dealing with a lot of optional arguments, it’s better to instead call the function with an object like so:

function printDetails(person) {
  const age = person.age ? person.age : 0;
  const country = person.country ? person.country : 'Ghana';

  console.log(`Hello ${person.name} from ${country} with age ${age} years`);
}

printDetails({ name: 'peter', age: '29' });

I’ve put the condition between () here like so: (person.age ? person.age : 0).
in this case the parentheses work a bit like parentheses work in math. If you do 5 x (5 + 6) in math, it will do (5 + 6) first in isolation. The same counts for our condition. Without the parentheses, some browsers might interpret the condition side to be const age = person.age (effectively testing if we were able to assign a variable), which is not what we want to test here.

When we run this we get:

$ node functions.js
Hello Peter from Ghana with age 29 years

The function we wrote so far does 2 things:

It’s often much better if a function is really good at doing only one or two things. Let’s see if we can move that console.log out instead.

function printDetails(person) {
  const age = person.age ? person.age : 0;
  const country = (person.country
    ? person.country
    : 'Ghana')`Hello ${person.name} from ${country} with age ${age} years`;
}

const message = printDetails({ name: 'peter', age: '29' });
console.log(message);

When we save and run this we’ll see the following:

$ node functions.js

Hey, what happened? Well the function we ran didn’t actually return anything. Let’s fix that.

function printDetails(person) {
  const age = person.age ? person.age : 0;
  const country = person.country ? person.country : 'Ghana';

  return `Hello ${person.name} from ${country} with age ${age} years`;
}

const message = printDetails({ name: 'peter', age: '29' });
console.log(message);

When run:

$ node functions.js
Hello peter from Ghana with age 29 years

Awesome. Let’s do something weird:

function printDetails(person) {
  const age = person.age ? person.age : 0;
  const country = person.country ? person.country : 'Ghana';

  return `Hello ${person.name} from ${country} with age ${age} years`;
  console.log('You made it here boss!!!');
}

const message = printDetails({ name: 'peter', age: '29' });
console.log(message);

When we run this, that extra “You made it here boss!!!” isn’t shown:

$ node functions.js
Hello peter from Ghana with age 29 years

So when you return, you stop a function from executing from that point on as well! We can use that.

function printDetails(person) {
  if (!person.name) {
    return 'you forgot the name';
  }

  const age = person.age ? person.age : 0;
  const country = person.country ? person.country : 'Ghana';

  return `Hello ${person.name} from ${country} with age ${age} years`;
  console.log('You made it here boss!!!');
}

const message = printDetails({ age: '29' });
console.log(message);

When we run this we see:

$ node functions.js
you forgot the name

Stopping functions from executing this way is called guard clausing.

You can simplify the above even more if you want. The following two lines both stop and return the code.

if (!person.name) {
  return 'you forgot the name';
}
if (!person.name) return 'you forgot the name';

When you deal with if-statements on a single line you can actually just leave out the function body marking { }. This is only possible from ECMAScript 2015 onward though.

Git away

It’s good to commit this work now, You’ve been creating a file with some function logic. It’s good to commit that (and possibly even put it on Github) so you can look at these things later when you forget how something worked (happens to me all the time!).

So open up your terminal, cd to the project and do something like this:

git add .
git commit -m "Adding some functions"

Github

Final remarks

You made it through todays lab! Go to WhatsApp and post something like “lab 1 is done!” for eternal glory (and my ability to see if I’m not making things too complicated).

We covered a lot of ground though and maybe you want to read a bit more. It’s not actually bad to try this lab 2 times. I’ve also hidden links to more examples when I mentioned hard-to-understand words in a few different places. Feel free to check them out.

Next week we’ll dive into advanced objects and classes. See you next week!