JS Crash Course
// Print to the console like this. It works both in the browser and node.
console.log("Hi, class!");
// Most expressions work exactly as in Java. There are some gotchas though!
console.log(2 * 3 + 1);
// Declarations do not have types. Use "let" to declare a regular variable.
let x = 2 * 3 + 1;
console.log(x);
x = "foo"; // a different type
console.log(x);
// VM has to do something when types are mixed in appropriately.
// In general, the VM tries to "do its best" to make it work.
console.log('20' - 15); // *illegal* in Java, but prints 5 here!
console.log('abc' - 15); // prints NaN because abc is not a number
console.log('20' + 15); // prints 2015
// Variables start out with the value "undefined" if not given one.
let z;
console.log(z); // prints undefined
// Use "const" to declare a variable that cannot change values. It must be
// assigned a value immediately.
const y = 2 * 3 + 1;
console.log(y);
//y = 2; // will fail!
// Can retrieve the type of a variable using the "typeof" operator, which
// returns a string: undefined, null, number, string, bigint,
console.log(typeof 1); // prints "number"
console.log(typeof undefined); // prints "undefined"
console.log(typeof false); // prints "boolean"
console.log(typeof "foo"); // prints "string"
// For equality, use "===" not "==". The latter tries to make things of
// different types into the same type before comparing.
console.log("0" === 0); // prints false
console.log("0" == 0); // prints true!
console.log("" == 0); // prints true!
// Like Java, "===" is value equality on primitive types and reference equality
// on reference types. Unlike Java, strings are primitive types.
console.log("foo" === ("f" + "oo")); // prints true
// We mentioned gotchas above. The most important one is division!
console.log(7 / 3); // watch out!
// Adding an "n" suffix makes the type "bigint", where division works properly.
console.log(typeof 7n); // prints "bigint"
console.log(7n / 3n); // prints 2n
// Explicitly converting to a string will print the way you want.
console.log(String(7n / 3n));
// Can also convert using Number, BigInt, etc.
console.log(3n === 3); // prints false
console.log(Number(3n) === 3); // prints true
console.log(3n === BigInt(3)); // prints true
// With number, you can do this by rounding down (but use bigint instead).
console.log(Math.floor(7 / 3));
// Most of Java's Math functions are provided as well.
console.log(Math.sqrt(9));
console.log(Math.sin(1));
// Strings are primitive types with built-in array-like indexing.
const s = "abc";
console.log(s[1]); // prints "b"
// Strings can be compared alphabetically using "<":
console.log("apple" < "orange"); // prints true
// Characters are represented as length-1 strings.
console.log(typeof s[1]); // prints "string"
// Also includes some Java methods, but it's bad style to use them.
console.log(s.charAt(1)); // prints "b"
// One exception is charCodeAt, which returns a number.
console.log(s.charCodeAt(1)); // prints 98 (UTF-8 encoding of '1')
// Literals can use either single or double quotes.
console.log("foo");
console.log('foo');
// Usually use the one that allows you to avoid escaping quotes.
console.log("Did you say \"there\" or \"their\"?");
console.log('Did you say "there" or "their"?');
// Template literals allow values to be substituted.
console.log(`The alphabet starts "${s}"...`); // The alphabet starts "abc"...
// If statements must allow anything to be used as a condition (since there is
// no type checker to make sure it's a boolean). This can be useful.
let t;
// .. some code that might set x to a string ...
if (!t)
console.log("t is not defined");
// Sometimes this works...
t = "a";
if (!t)
console.log("t is not defined");
// But it's also a common source of bugs.
t = "";
if (!t)
console.log("t is not defined");
// These things evaluate to false.
console.log(Boolean("")); // prints false
console.log(Boolean(0)); // prints false
console.log(Boolean(NaN)); // prints false
// So use booleans only in conditions.
if (t !== undefined)
console.log("t is not defined");
// Nice literal syntax for creating records with fields. Retrieving the value
// of a field is the same as in Java.
const r = {x: 1};
console.log(r.x); // prints 1
// Can think of Math as a record with field "sqrt"...
// These are called "objects" although their CS name is "records".
console.log(typeof {x: 1}); // prints "object"
// Like Java, "===" is value equality on primitive types and reference equality
// on reference types (records, arrays, and instances of classes).
console.log({x: 1} === {x: 1}); // prints false
// Also possible to retrieve fields using [..] syntax, but it's uglier.
console.log(r["x"]); // prints 1
// Can check for the presence of a field using "in", but there are gotchas.
// Usually, when you are doing this, you are making a mistake...
console.log("x" in r); // prints true
console.log("y" in r); // prints false
console.log("toString" in r); // prints true
// When the fields of the record are not known ahead of time, use a Map.
const M = new Map();
M.set("a", 1);
M.set("b", 5);
console.log(M.get("a")); // prints 1
console.log(M.get("b")); // prints 5
console.log(M.get("toString")); // prints undefined
M.set("a", 2);
M.set("c", 3);
console.log(M.get("a")); // prints 2
console.log(M.get("c")); // prints 3
// JavaScript also provides a set class.
const S = new Set();
S.add("a");
S.add("b");
console.log(S.has("a")); // prints true
console.log(S.has("c")); // prints false
S.add("c");
console.log(S.has("c")); // prints true
// Array elemnts are accessed like Java, but simpler to create. Note again that
// there are no type declarations, so elements can have any type.
const A = [1, 2, "foo"]; // no type restriction!
console.log(A[2]); // prints “foo”
// Add and remove using push and pop
A.pop();
console.log(A); // prints [1, 2]
A.push(3);
console.log(A); // prints [1, 2, 3]
// Length field stores the length of the array.
console.log(A.length); // prints 3
A.pop();
console.log(A.length); // prints 2
// Arrays are a special kind of object.
console.log(typeof A); // prints "object"
// Can distinguish the latter two using Array.isArray
console.log(Array.isArray(A)); // prints true
console.log(Array.isArray({x: 1})); // prints false
// Map and Set constructors take array giving the initial value.
const T = new Set(["a", "b"]);
const N = new Map([["a", 1], ["b", 5]]);
// Functions are first-class objects, storable in a const. They can also be
// declared with the "function" keyword, but like "var", we will avoid that.
const add3 = (x, y, z) => {
return x + y + z;
};
console.log(add3(1, 2, 3)); // prints 6
// No curly braces needed for a simple "return" statement.
const add2 = (x, y) => x + y;
console.log(add2(1, 2)); // prints 3
// Class syntax is similar to Java, but again, there are no types. The
// constructor is called "constructor", not the class name.
class Pair {
constructor(x, y) {
this.x = x;
this.y = y;
}
// We will declare methods like this. (Another syntax exists but has problems)
distTo = (p) => {
const dx = this.x - p.x;
const dy = this.y - p.y;
return Math.sqrt(dx*dx + dy*dy);
};
}
const p = new Pair(1, 2);
const q = new Pair(2, 2);
console.log(p.distTo(q)); // prints 1