<<

Introduction to JavaScript

Niels Olof Bouvin

2 Overview

A brief history of JavaScript and ECMAScript JavaScript for developers The JavaScript ecosystem Getting access to JavaScript Some language basics A look at the Node.js standard

3 The origins of JavaScript

JavaScript began its life in 1995, when Brendan Eich, working at Netscape, on a deadline created the frst version of the language in 10 days it was originally known as ‘Mocha’ or ‘LiveScript’, but was eventually named ‘JavaScript’ as the Java was very popular at the time In August 1996, Microsoft debuted JScript, and trying to not lose the initiative, Netscape turned JavaScript over the ECMA standard organisation thus, the official name of the language became ECMAScript ECMAScript 1 was standardised in June 1997 the current standard is ES2016, or ES6 for short

4 JavaScript: backwards compatibility is king

Based on the immense weight of JavaScript code already deployed across the Web, the powers behind JavaScript has sought to maintain compatibility This means that all design decisions of the past, good, bad and worse, are still with us However, if we do not have to maintain a legacy system, we can choose to look and move forward Therefore, we will, in this course, only and exclusively use ES6 and onwards standards, because we are not bound by the bad old days

5 Overview

A brief history of JavaScript and ECMAScript JavaScript for Java developers The JavaScript ecosystem Getting access to JavaScript Some language basics A look at the Node.js standard library

6 JavaScript for Java developers

There are many superfcial similarities between Java and JavaScript, as they, syntax-wise, share a common ancestor in They are however at heart quite different, and while you certainly will beneft from your Java knowledge, you should also be aware that this is a new language with a different environments and different rules and conventions

7 Java vs JavaScript

Object-oriented, class Object-oriented, relaxed, based design prototype based Statically and strongly Relaxed and dynamically typed typed Compiled Interpreted Lambdas were only just Functions were always introduced in Java 8 frst-class objects Requires a JVM to run, Usually either browser or rarely seen in browsers Node.js based these days

8 Object-oriented, but different

Java is class-based: Objects are instances of Classes There are no classes in JavaScript per se, only primitive types and objects. An object may point to another object as its prototype The Java approach of defning class hierarchies for development is foreign to JavaScript Syntax has been introduced in ES6 to make JavaScript appear more traditionally class-based as you'll see shortly

9 Typing

In Java, you defne what type a variable has, and the compiler will hold you to it In JavaScript, the type is inferred, and you  node can change your mind without JavaScript > let a = 2 undefined complaining, and if you have done > a 2 something wrong, it will fail when it runs > a = '2' '2' > a This is a potential minefeld, so it is '2' important to be disciplined and to use tools to check your code TypeScript, a superset of JavaScript created by Microsoft, improves on JavaScript by, among other things, adding additional type information

10 Compiled or interpreted

Java is compiled into Bytecode, packed into JAR fles, and then distributed JavaScript is distributed as text, and interpreted upon delivery There used to be a big performance gap, but that has closed with modern JavaScript engines It means, however, that the checks made by the Java compiler will frst be made when the JavaScript code is interpreted or when it is run thus, testing quickly becomes really important with JavaScript projects

11 Objects, functions or both

In Java, everything has to be defned within a class, whether it makes sense or not In JavaScript, you can just do things, usually through functions, and you can hand functions around like the completely ordinary values they are If you want to use objects and inherit stuff from other stuff, you can do that, too

12 Overview

A brief history of JavaScript and ECMAScript JavaScript for Java developers The JavaScript ecosystem Getting access to JavaScript Some language basics A look at the Node.js standard library

13 The JavaScript ecosystem

JavaScript is one of, if not the, most popular programming languages in the world But, compared to, e.g., Java, JavaScript does not have a strong standard library of functionality ready to use Thus, an absolute mountain of supporting libraries has been created by thousands and thousands of developers this is good, because there’s probably a library to solve your problem this is bad, because you may have to wade through dozens if not hundreds of poorly maintained libraries to fnd The One (or have to choose between multiple valid, fully functioning solutions). It also leads to the “framework of the week” phenomenon We’ll try to keep things as simple as possible in this course, only including libraries if absolutely necessary

14 JavaScript ES6 and onwards

The current standard for ECMAScript It is by now widespread and much nicer than previous versions BUT! Some of the material you’ll encounter (even in this course) will still be using some of the olden ways I'll try to highlight when I differ from what you have read and I'll usually point to the Eloquent JavaScript book or the MDN site

15 Overview

A brief history of JavaScript and ECMAScript JavaScript for Java developers The JavaScript ecosystem Getting access to JavaScript Some language basics A look at the Node.js standard library

16 Getting access to JavaScript

JavaScript is available directly in your Web browser, typically accessed through a ‘Developer’ menu you may need to explicitly enable this menu somewhere in ‘Settings’ or ‘Preferences’ Alternatively, it can installed and used locally through Node.js, which is where we will start see the Tools page on the course site for installation it can be launched from the command line with ‘node’

17 Starting out: The JavaScript REPL

(Read, Eval, Print, Loop) If we start node without any arguments, or begin typing in the JavaScript console in a Web browser, we begin in the REPL:

Statements are evaluated line by line as they are entered, no compilation necessary this is a great way to test out code, check proper syntax, or mess with a live Webpage REPLs are found in most interpreted languages, and they are excellent tools, as they allow you to interact directly with your or others’ code

18 Following along

I would like you to follow along with the code, so download the zip-fle, open VSC, load the fles, open the terminal (View→Terminal), and run the code using node You should also know that the code examples in the Eloquent JavaScript book are also interactive—please use it, it is a great learning tool

19 Overview

A brief history of JavaScript and ECMAScript JavaScript for Java developers The JavaScript ecosystem Getting access to JavaScript Some language basics A look at the Node.js standard library

20 Basic syntax Beginning a JavaScript program with this line signals to the system

'use strict’; that the following is written in the const greeting = 'Hello World’; modern, ES6 style. You should console.log(greeting); const x = 2; always do this—it can catch quite if (x < 4) { console.log('x is a small number’); a few errors } else { console.log('x must be pretty big’); } You can enter the above directly into the Node.js REPL or the JavaScript Console in your browser try it—it's a good way to get a handle for the syntax and try things out One statement/expression per line;

21 Types in JavaScript

Primitive types Objects boolean everything else, including the object number counterparts: string Boolean, Number & String

Symbol > typeof true 'boolean' null > typeof 42 undefined 'number' Wait, what? > typeof 'hi!' 'string' this is one of those things considered > typeof null 'object' awful about old design decisions in > typeof undefined JavaScript 'undefined' > typeof Symbol() it is a primitive type 'symbol'

22 Types are inferred, not declared

> let a = 2 undefined > typeof a 'number' > a = '2' '2' > typeof a 'string' >

You can bind one type of value to a variable, and later bind another type you shouldn't, but you can. (Please do not) This is one of those things, where tools become useful 23 What is a number?

Sane programming languages differentiate between integers and foating point numbers in many cases, integers are sufficient, faster, and more compact than foats Yet, JavaScript knows only Numbers, which are foats JavaScript engines make a guess of it and usually gets it right for efficiency's sake, there is now direct support for arrays of specifc types of numbers, this is very important in, e.g., audio or graphics applications, where performance is crucial

24 Collections

> let myList = [1, 2, 3] > let myMap = new Map() undefined undefined > myList.length > myMap.('a', 'foo') 3 Map { 'a' => 'foo' } > myList[0] > myMap.set('b', 2) 1 Map { 'a' => 'foo', 'b' => 2 } > myList.push(4) > myMap.set(3, 'a') 4 Map { 'a' => 'foo', 'b' => 2, 3 => 'a' } > myList > myMap.get('a') [ 1, 2, 3, 4 ] 'foo' > myList.pop() > myMap.has(3) 4 true > myList > let mySet = new Set() [ 1, 2, 3 ] undefined > typeof myList > mySet.add('a') 'object' Set { 'a' } > mySet.add('b').add('c') Set { 'a', 'b', 'c' } Chainable! > mySet.add('a') Set { 'a', 'b', 'c' } > mySet.has('b') true Arrays, Maps, Sets: should be familiar to Java experts! 25 Control statements

'use strict'; 'use strict'; const x = 2; const myTerm = 'quux'; if (x < 4) { switch (myTerm) { console.log('x is a small number'); case 'foo': } else { console.log(1); console.log('x must be pretty big'); break; } case 'bar': console.log(2); break; case 'baz': console.log(3); break; case 'quux': console.log(4); break; default: console.log('?'); }

Nothing new here, I expect 26 Looping and iterating

'use strict’; 'use strict’; for (let i = 0; i < 5; i++) { const myPosse = ['Alice', 'Bob', ‘Carol']; console.log(i); for (let person of myPosse) { } console.log(person); }

The basic for loop should be familiar to you for of can iterate through iterables, including Arrays, Maps, and Sets, and is in general the preferred version of for 27 Strings and variables, old and new

'use strict’; const first = ‘Jane'; const last = ‘Doe'; The new console.log('Hello ' + first + ' ' + last + ‘!!'); method is much cleaner, easier to read, less error-prone, and

'use strict’; in all ways const first = ‘Jane'; superior to the const last = ‘Doe'; old approach console.log(`Hello ${first} ${last}!`); if you can fnd '`' on your keyboard

28 var: declaring variable the old way

Back in the bad old days, scope

(i.e., from where in a program a 'use strict’; variable can be seen) was a bit var x = 3; function func (randomize) { odd in JS if (randomize) { var x = Math.random(); most programming languages have block scope, return x; } but JavaScript had function scope return x; } a variable declared with var is scoped within the console.log(func(false)); inner-most function it fnds itself in, and 'hoisted', i.e., auto-declared from the top of that function This is an example where having a tool to assist your coding is invaluable

29 let & const: the new & improved way

If you use let instead, you get block scoping instead—much 'use strict’; let x = 3; easier to handle and understand function func (randomize) { if (randomize) { let x = Math.random(); const is used whenever a return x; variable is not expected to } return x; change } console.log(func(false)); it is a good habit to use const whenever possible, because that can catch inadvertent errors the scoping rules are as with let You should endeavour to always use let and const if at all possible

30 let & var, another demonstration

'use strict’;

let x = 10; if (true) { Mixing let and var can lead to let y = 20; var z = 30; confusion, as var declared console.log(x + y + z); } variables are hoisted to the top of console.log(x + z); their (functional) context stick to let and const

31 Functions

'use strict’;

function myF1 () { return 1; } Functions are frst-class const myF2 = function () { return 2; citizens in JavaScript } function myFxy (fX, fY) { return fX() + fY(); They can be created, } console.log(myF1(), myF2()); assigned to variables, and console.log(myFxy(myF1, myF2)); passed around as arguments to other functions

32 Arguments and default arguments 'use strict’;

You can, of course, function greet (greeting = 'Hi', pass arguments to person = 'friend') { return `${greeting}, ${person}`; functions } function sum (...numbers) { let total = 0; These can have for (let n of numbers) { total += n; default values, if you } return total; wish } console.log(greet()); console.log(greet(‘Hello')); The … construct console.log(greet('Howdy', ‘Pardner')); allows you to have as console.log(sum(1, 2, 3, 4, 5, 6, 7, 8, 9)); many arguments, as you desire …args must be last

33 The arrow function

Functions are used a lot as arguments in JavaScript 'use strict’;

The => construct makes it const doubler = x => (2 * x); easy to create anonymous const adder = (x, y) => x + y; console.log(doubler(3)); functions console.log(adder(3, 4)); console.log((x => 3 * x)(3)); return is implied, but you can add it if you want, including braces Functions can also just be created in situ

34 Using functions to operate on arrays

'use strict’; const arr = [1, 2, 3, 4]; console.log(arr.map(x => 2 * x)); console.log(arr.filter(x => x > 2)); console.log(arr.reduce((acc, c) => acc + c));

Arrays support a number of methods to operate on the entire array, including map, flter, and reduce this can be a very convenient way to, e.g., flter an array of strings This is a place where => functions come into their own 35 Testing for equality

Assignment or binding in JavaScript is '=' '==' used to be the equality operation, but it is badly broken, and you should never use it (it converts type!) '===' and '!==' are the proper operations to use 36 Classes and objects in JavaScript ES6

'use strict'; class ColorPoint extends Point { constructor (x, y, color) { class Point { super(x, y); constructor (x, y) { this.color = color; this.x = x; } this.y = y; } toString () { return `${super.toString()} in ${this.color}`; toString () { } return `(${this.x}, ${this.y})`; } } const cp = new ColorPoint(30, 40, 'green'); } console.log(cp.toString()); console.log(cp instanceof Point);

Strictly speaking, classes are functions in JavaScript ES6, but a bit of syntactic sugar has been introduced to have familiar constructs for most 37 Getters and setters

'use strict'; get y () { class Point { return this._y; constructor (x, y) { } this._x = x; this._y = y; set x (x) { } this._x = x; } toString () { return `(${this.x}, ${this.y})`; set y (y) { } this._y = y; } get x () { } return this._x; const p = new Point(30, 40); } console.log(p.toString()); console.log(`p.x = ${p.x}`);

If you are so inclined, it is also possible to create getters and setters in JavaScript 38 Overview

A brief history of JavaScript and ECMAScript JavaScript for Java developers The JavaScript ecosystem Getting access to JavaScript Some language basics A look at the Node.js standard library

39 JavaScript does not work in isolation

As we have seen, JavaScript is quite closely integrated into the Web browser, which is exposed through the Document object When it comes to programs outside the browser, JavaScript, in the form of Node.js, relies on its standard library to access the world such as the fle system, networking, databases, etc.

40 JSON: Exchanging data in JavaScript

The predominant format used to transmit data in JavaScript programs is JavaScript Object Notation it has spread far beyond JavaScript these days used for fles, and for encoding data to be sent over the Internet It is quite close to JavaScript in syntax, and can be written and read directly It can used to translate arrays and Objects into strings and back again but curiously enough neither Maps nor Sets, but you’ll fx that!

41 The JSON object: stringify() & parse()

 node > const myList = [1, 2, 'tre', 4, 'fem'] undefined > myList [ 1, 2, 'tre', 4, 'fem' ] > const myListJSONified = JSON.stringify(myList) undefined > myListJSONified ‘[1,2,”tre",4,"fem"]' > typeof myListJSONified ‘string’ > const myListReturned = JSON.parse(myListJSONified) undefined > myListReturned [ 1, 2, 'tre', 4, 'fem' ] > myListReturned instanceof Array true

The JSON object has two methods: stringify & parse stringify can take a and return it as a JSON formatted string parse can take a JSON formatted string and return it as a JavaScript object 42 Writing to a fle

Files are important, because they offer persistence JavaScript does not inherently have the ability to deal with fles (in truth, it does not have the ability to deal with the outside world at all) this is where the Node.js standard library becomes handy We will need to use the fle system module, ‘fs’ for short

43 Modules

Modules in Node.js are the equivalent of packages in Java a rich set of objects and functions (classes in Java) that you can use in your programs In Java, you import a package; in Node.js, we require it Node.js ships with its standard library, and in addition there is an enormous number of third-party modules

44 Dealing with fles

Writing to or reading from a fle is a three stage process: you open the fle you write to it, or read from it you close the fle Things can go wrong! perhaps the fle is not where we expected (or there at all) perhaps we do not have permission to change or read the fle perhaps something goes wrong as we are reading or writing this calls for exceptions

45 Writing ‘Hello world’ to a fle

'use strict'; const fs = require('fs'); const fileName = 'message.txt'; fs.open(fileName, 'a', (err, fd) => { if (err) throw err; fs.appendFile(fd, 'Hello world!\n', 'utf8', (err) => { fs.close(fd, (err) => { if (err) throw err; }); if (err) throw err; }); });

Isn’t that a lot of code to do just that? well… yes, but there is a reason, and it has to do with the fundamentals of JavaScript and Node.js interacting with the world 46 What’s with all the arrow functions?

Node.js is a single threaded, non blocking I/O, event- driven system When programs are single threaded, they usually only do one thing at a time, so if they open a fle, they have to wait for the fle to be opened (a long time for a computer), while they do nothing (i.e., they freeze) In Node.js, we don’t wait—we start things, and hand them instruction on what to do when they are ready function are of course a splendid way to give instructions

47 Doing work in Node.js

One way to think of this is a cashier in a fast-food restaurant receiving orders from customers some jobs the cashier can do immediately and does so most orders are added to the list (or queue) of things to do for the cooks working behind the counter a cook will take an order off the queue, cook it up, and once fnished, return the ordered item to the front, where the cashier hands the customer the food while the cooks are working, the cashier can receive new orders from the customers We are the customers, dealing with the cashier The cashier leaves, when the queue is empty, the last order fulflled, and all the immediate jobs are done

48 Opening the fle

fs.open(fileName, 'a', (err, fd) => { if (err) throw err; // . . . })

“Open the fle named fleName in append mode, and call this function when the fle is ready or something has gone wrong” the last argument, the function, is the callback function, and it’s called from fs.open A callback function often takes two arguments: an error, and the result of the operation, if there is one If there is an error, we throw an exception You’ll see this pattern many times in JavaScript 49 Opening the fle

fs.appendFile(fd, 'Hello world!\n', (err) => { fs.close(fd, (err) => { if (err) throw err; }) if (err) throw err; }) “Append the text ‘Hello world!’ to the fle identifed by fd, and call this function when done (or something has gone wrong)” there is no result returned here, but things can still go wrong, so the callback function still has an err argument, which is set to null if there was no error (and null is false) Whether the string has been written or not, we need to close the fle (we know it has been opened) If there was an error with appending the fle, we throw an error 50 Reading the fle back in again

'use strict’; const fs = require(‘fs'); fs.readFile('message.txt', 'utf8', (err, data) => { if (err) throw (err); // handle any errors console.log(data); // do the thing })

Simpler, but still the same principle: start something, and give it the instructions on what to do, when ready 51 Will this work?

'use strict’;

const fs = require(‘fs');

let theMessage; fs.readFile('message.txt', 'utf8', (err, data) => { if (err) throw (err); theMessage = data; }) console.log(theMessage);

What is going on here? 52 Let’s add some time to track the code 'use strict’;

const fs = require(‘fs’);

const start = Date.now(); let theMessage; fs.readFile('message.txt', 'utf8', (err, data) => { if (err) throw (err); theMessage = data; console.log(`File is read: ${Date.now() - start} ms`); console.log(data); }) console.log(theMessage); console.log(`Last line of code: ${Date.now() - start} ms`);

All the immediate jobs have been done by the cashier then the cook brings the ordered item to the front 53 Handling callbacks

So, you should deal with the results of a computation in the callback function but what if that function also has a callback • and that function also has a callback • and that function also has a callback • and that function also has a callback • … Then you are in what in JavaScript is known as ‘callback hell’ and that can be a bit of a mess, because it is hard to keep track of opening and writing to a fle required three levels of callback—it can be much worse but don’t worry: there is a better way, and we’ll get back to this problem later

54 Wrapping up

JavaScript has undergone a tremendous development since its inception, perhaps more than any other Web technology (it was also in need of some advancement) Used in its most modern incarnation, ES6, it is a perfectly pleasant language, especially if paired with a bit of tooling to check for potential bugs It is available everywhere you can fnd a Web browser, and it's easy to get started

55