javascript is a programming language you can use to program web pages and command-line tools and servers
We'll be using node on the command-line to learn javascript.
Download and install node from:
Now let's make a program. Put this text into a file called robot.js:
console.log('BEEP BOOP')
Now use node
to run your program:
$ node robot.js
BEEP BOOP
console.log(...)
is a function that
prints its arguments to stdout followed
by a newline (\n
) character
'BEEP BOOP'
is a string.'BEEP BOOP'
is an argument to theconsole.log()
function.
Note the single quotes on each side.
You can use double quotes too: "BEEP BOOP"
Sometimes an "argument" is called a "parameter".
In the previous program, we had a single statement. You can have multiple statements, each on their own line:
console.log('Such')
console.log('wow.')
Now save this code to a file suchwow.js
and run it with node
:
$ node suchwow.js
Such
wow.
You might also see programs that use semicolons to separate statements:
console.log('Such');
console.log('wow.');
Semicolons are optional. There are some cases where they are necessary, but this is rare in practice.
Both including and omitting semicolons are popular code styles.
Another kind of statement is a variable declaration:
var x = 5
var y = 111
console.log(x * y)
var a = 'beep'
var b = 'boop'
console.log(a + b)
which prints:
$ node vars.js
555
beepboop
Variables are containers that can hold values.
Strings like 'beep'
and numbers like 5
are values.
We used the *
operator to multiply
two numbers.
Here are some other operators you can try with numbers:
+
- add-
- subtract*
- multiply/
- divide%
- modulo (the remainder after division)
There is another way of evaluating expressions as you type them in: the REPL.
The REPL is like calculator mode.
Just type node
to get into a REPL.
Then type an expression and you will see its result:
> 1+2
3
Type ctrl+d to exit the REPL.
You can change the value stored in a variable at any time by assigning a new value.
var x = 5;
x = x + 10;
console.log(x);
which prints 15
:
$ node x.js
15
There is a shorthand for running an operator
and saving the result back to a variable.
Instead of x = x + 10
we can do
x += 10
instead:
var x = 5
x += 10
console.log(x)
Just take one of the arithmetic operators
from earlier and add an =
at the end to
do an update "in place":
+=
- add in place-=
- subtract in place*=
- multiply in place/=
- divide in place%=
- modulo in place
There are two other operators for convenience:
-
x++
- increment x by 1 in place Same as:x += 1
orx = x + 1
-
x--
- decrement x by 1 in place Same as:x += 1
orx = x + 1
You might also see ++x
and --x
which
are similar to x++
and x--
but have
slightly different uses. More on them later.
The comparison operators all return a boolean:
===
- strict equality!==
- not strict equality<
- less than<=
- less than or equal to>
- greater than>=
- greater than or equal to
You might also see coercive equality operators:
==
- coercive equality!=
- not coercive equality
but you should avoid these operators until learning about type coercion.
var x = 5;
console.log(x < 6);
console.log(x === 2);
console.log(x !== 5);
console.log(x >= 5);
output:
$ node cmp.js
true
false
false
true
&&
- AND||
- OR!
- NOT (the opposite truth value)
!
is a "unary" operator like ++
and --
because it binds to a single value.
&&
and ||
are "binary" operators
because they bind to two values:
one on the left and one on the right.
var x = true
var y = false
console.log(x && y) // false
console.log(x || y) // true
console.log(!(x || y)) // false
console.log(!y) // true
outputs:
$ node bool.js
false
true
false
true
By the way, //
is the comment operator.
Anything that follows //
on a line is
ignored by the computer.
You can even have whole blocks of comments
by putting text between /*
and */
:
// this is a comment
console.log('beep boop'); // wow
/*
and this is a comment that
spans multiple
lines
*/
You can make a block of code execute when
a conditional expression is true using an
if
statement.
The conditional expression is the expression
surrounded by parenethesis following the word
if
:
var x = 5;
if (x < 10) {
console.log('wow');
}
this program will print:
$ node if.js
wow
but if we change the program to be:
var x = 11;
if (x < 10) {
console.log('wow');
}
then it won't print anything since the conditional expression evaluated to false:
$ node if.js
You can put an else
statement after an
if
statement to tell the computer what
to do if the if
conditional expression
wasn't true:
var x = 11;
if (x < 10) {
console.log('wow');
}
else {
console.log('cool');
}
will print:
$ node else.js
cool
Use else if
to chain together fall-through cases:
var x = 22;
if (x < 10) {
console.log('wow');
}
else if (x === 22) {
console.log('twotwo');
}
else {
console.log('cool');
}
var x = 5;
if (x < 5) {
console.log('lt');
}
else {
var y = x * 333 + 22;
if (y > 1000) {
console.log('y > 1000!!!');
}
else {
console.log('y otherwise...');
}
}
Now is a good time to talk about indentation.
First, you'll need to pick an amount of indentation to use for each level.
if (true) {
if (true) {
if (true) {
// ...
}
}
}
if (true) {
if (true) {
if (true) {
// ...
}
}
}
However you choose to indent, be consistent!
Your code will be much easier for others and yourself to read.
Remember to line up closing braces at the same level as opening statements!
Arrays are ordered lists of values. You can make an array with square brackets:
var arr = [ 3, 2, 5 ]
console.log(arr)
To get at individual elements, use square brackets and an integer index starting from zero:
var arr = [ 1, 4, 9 ];
console.log('first:', arr[0]);
console.log('second:', arr[1]);
console.log('third:', arr[2]);
outputs:
first: 1
second: 4
third: 9
You can use variables for indexing too, not just constant integers:
var arr = [ 1, 4, 9 ];
var n = 2;
console.log(arr[n]);
prints:
9
To get the length of an array, just use .length
:
var arr = [ 1, 4, 9 ];
console.log(arr.length);
which is the same as:
console.log([ 1, 4, 9 ].length);
To add an item to the end of an array,
use arr.push()
:
var arr = [ 8, 1 ];
arr.push(5);
console.log(arr);
prints:
[ 8, 1, 5 ]
arr.push()
is an example of a builtin
method, a function you can call that has
been defined by the language itself.
Later we'll see how to inspect what methods are available.
You can also remove an element from the
end of an array with arr.pop()
:
var xs = [ 10, 6, 3 ];
console.log('popped:', xs.pop());
console.log('now xs=', xs);
prints:
popped: 3
now xs= [ 10, 6 ]
Remove an element from the beginning of an array with shift:
var xs = [ 1, 2, 3 ];
console.log('shifted:', xs.shift());
console.log('xs=', xs);
Return a new array between a start index and an end index. If you don't provide an end index, the array length is used.
var xs = [ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i' ];
console.log(xs.slice(2, 3));
console.log(xs.slice(2));
prints:
[ 'c', 'd', 'e' ]
[ 'c', 'd', 'e', 'f', 'g', 'h', 'i' ]
To see everything you can do with arrays, visit:
So far, all of our examples have used hard-coded variables defined in the source code itself.
console.log(process.argv);
will print:
$ node args.js one two three
[ 'node',
'/home/substack/projects/workshops/args.js',
'one',
'two',
'three' ]
The first 2 arguments aren't too useful, just node
and the
full path to our script, but the remaining arguments are
everything that follows args.js
on the command-line.
To get only the useful arguments, we can use .slice(2)
:
var args = process.argv.slice(2);
console.log(args);
now we can do:
$ node args.js beep boop xyz
[ 'beep', 'boop', 'xyz' ]
or to get at a single argument, you could use square brackets:
var x = Number(process.argv[2]);
var y = Number(process.argv[3]);
console.log(x + y);
prints:
$ node add.js 3 5
8
Note that every element in process.argv
is a string, so we
can use the built-in Number
function to convert from a
string to a number.
We've already been using some objects:
process
is an object with a propertyargv
that is an array.console
is an object with a propertylog
that is a function.
Objects map keys to values.
Like how a phone book maps names to telephone numbers:
key value
----------------------|---------
Benjamin Franklin | 123-4142
Alexander Graham Bell | 214-6821
Marie Curie | 615-2904
To create the same structure in javascript we could do:
var phonebook = {
'Benjamin Franklin': '123-4142',
'Alexander Graham Bell': '214-6821',
'Marie Curie': '615-2904'
};
If a key is only letters, numbers, underscores, and dollar signs (but doesn't start with a number), you can leave off the quotes:
var obj = {
abc: 555,
def: 123,
x1: 1000,
y1: 5000,
$x: 4444,
"x y z": 12 // otherwise you'll need to use quotes
}
This way of building objects is sometimes called "object literal" syntax.
Once an object exists, you can reference an individual value
by its key using a .
followed by the key name. Here we use
obj.y
to get at the y
key:
var obj = { x: 7, y: 8, z: 9 };
console.log(obj.y);
will print:
8
Reference a key with a .
followed by a key then use an
equal sign to create a new value under that key:
var obj = { a: 3, b: 4 };
obj.c = 5;
console.log(obj);
prints:
{ a: 3, b: 4, c: 5 }
The same obj.c = 5
syntax works even if a key already
exists:
var obj = { x: 500, y: 200 };
obj.y = 300;
console.log(obj);
prints:
{ x: 500, y: 300 }
All of the assignment operators work for object keys just like for variables!
var obj = { x: 500, y: 200 };
obj.y += 1000;
obj.x *= 3;
console.log(obj);
prints:
{ x: 1500, y: 1200 }
Using the .
operator to access keys is handy, but what
about special characters in keys?
We can use square brackets with a string to reference keys with special characters:
var obj = { 'a b c': 123, 'x#y*z': 456 };
console.log(obj['a b c']);
prints:
123
We can also use square brackets to reference dynamic keys. For example, if we want to load a key from a variable:
var key = 'def';
var obj = {
abc: 555,
def: 333,
xyz: 222
};
console.log(obj[key]);
prints:
333
Everything we can do with dot (updates, assignment operators, etc) works with square bracket notation.
To delete items from an object, use the delete
keyword:
var obj = { a: 4, b: 5, d: 700, x: 6 };
delete obj.d;
console.log(obj);
prints:
{ a: 4, b: 5, x: 6 }
If you try to delete a key that doesn't exist, nothing happens.
Use Object.keys()
to get an array of all the keys that an
object has:
var obj = { x: 5, y: 6, abc: 3 };
console.log(Object.keys(obj));
prints:
[ 'x', 'y', 'abc' ]
Now that we've seen objects and arrays, it's worth noting that you can nest these data structures as much as you like.
To reference the nested properties, you can stack dot and square bracket notation to read keys and array indexes:
var root = {
a: 3,
b: [ { x: 4, y: 6 }, { d: 1, e: 2 } ],
c: { q: [ 7, 8, 9 ], r: [ 1, 2, 3 ]
};
console.log(root.a); // 3
console.log(root.b[1].e); // 2
console.log(root.c.q); // [ 7, 8, 9 ]
console.log(root.c.r[2]); // 3
Use a while loop to repeat a command while a conditional is true:
var x = 4;
while (x > 0) {
console.log(x);
x --;
}
prints:
4
3
2
1
This program will never stop!
while (true) {
console.log('wow');
}
But inside the loop we can use break
to quit the loop:
var x = 4;
while (true) {
console.log(x);
x --;
if (x <= 0) break;
}
prints:
4
3
2
1
For loops are like while loops but provide a place for initialization and an expression to advance the loop.
for (var i = 0; i < 4; i++) {
console.log(i);
}
prints:
0
1
2
3
Or you can jump by tens starting from 50:
for (var i = 50; i < 100; i += 10) {
console.log(i);
}
prints:
50
60
70
80
90
A very common use-case for for
loops is to loop over each
element in an array:
var xs = [ 'a', 'b', 'c', 'd' ];
for (var i = 0; i < xs.length; i++) {
console.log(xs[i]);
}
prints:
a
b
c
d
You can think of functions as little factories that take input as arguments and return output.
function add (x, y) {
return x + y;
}
console.log(add(3, 4));
prints:
7
You can define a function lower down in a file than where you use it too:
console.log(add(3, 4));
function add (x, y) {
return x + y;
}
Any variables declared inside a function are only accessible inside of that function.
function fff (a, b) {
var c = 500;
return a + b + c;
}
console.log(fff(3,4));
console.log(c); // will raise an error
Functions can appear in any expression. You can assign them to variables:
var add = function (a, b) {
return a + b;
};
console.log(add(5, 2)); // 7
When you declare functions in expressions you don't need to give them a name.
Because functions are ordinary values that can appear in expressions, you can pass a function as an argument to another function.
function binary (a, b, operator) {
return operator(a, b);
}
function add (a, b) {
return a + b;
}
console.log(binary(3, 4, add));
We could write the previous example with the add
function
declared inline:
function binary (a, b, operator) {
return operator(a, b);
}
console.log(binary(3, 4, function (a, b) {
return a + b;
}));
We could even define the binary function inline, although this is not very readable:
console.log(
function (a, b, operator) {
return operator(a, b);
}(3, 4, function (a, b) {
return a + b;
})
);
There are some built-in functions that accept functions as
arguments. .map()
takes a function that transforms the
contents of an array, creating a new array:
var first = [ 3, 4, 5 ];
var second = first.map(plusFifty);
console.log(second);
function plusFifty (x) { return x + 50 }
prints:
[ 53, 54, 55 ]
You can also use forEach
to loop over items in an array
without having to whip up a for
loop:
[ 7, 8, 9 ].forEach(function (x) {
console.log(x);
});
Functions can return any javascript value: numbers, strings, arrays, objects, even other functions!
When you return a function from another function, the variables you declare persist in the inner function.
function counter () {
var times = 0;
return function () {
times ++;
return times;
};
}
var c = counter(); // c is a function
console.log(c()); // 1
console.log(c()); // 2
console.log(c()); // 3
Another common pattern is to return an object with functions as values:
function Num (value) {
return {
add: function (x) {
value += x;
return value;
},
multiply: function (x) {
value *= x;
return value;
};
};
}
var n = Num(100);
console.log(n.add(5)); // 105
console.log(n.multiply(3)); // 315
Often, javascript APIs make use of callbacks:
var fs = require('fs');
fs.readFile('foo.txt', function (err, src0) {
fs.readFile('bar.txt', function (err, src1) {
console.log(src0.length + src1.length);
});
});
console.log(1);
var fs = require('fs');
fs.readFile('foo.txt', function (err, src0) {
console.log(3);
fs.readFile('bar.txt', function (err, src1) {
console.log(5);
console.log(src0.length + src1.length);
});
console.log(4);
});
console.log(2);
prints: 1, 2, 3, 4, 5
Only after the current block of code has "run to completion" do callbacks scheduled on the event loop execute.
Another way to create objects with properties is to use a constructor. The previous example is pretty much the same as:
function Num (value) {
this.value = value;
}
Num.prototype.add = function (x) {
this.value += x;
return this.value;
}
Num.prototype.multiply = function (x) {
this.value *= x;
return this.value;
}
var n = new Num(100);
console.log(n.add(5)); // 105
console.log(n.multiply(3)); // 315
n
is an "instance" of Num. You can make as many instances
as you like and they will all have separate values.
If you use a constructor, don't forget to use new
!
Here is one weird trick discovered by a bus driver for
making constructor instances without new
:
function Num (value) {
if (!(this instanceof Num)) return new Num(value);
this.value = value;
}
Num.prototype.add = function (x) {
this.value += x;
return this.value;
}
Num.prototype.multiply = function (x) {
this.value *= x;
return this.value;
}
var n = Num(100); // you don't need to remember `new` now
console.log(n.add(5)); // 105
console.log(n.multiply(3)); // 315
The javascript language has many features built into the basic types.
For example, did you know that for any string you can do:
console.log('beep boop'.toUpperCase());
which prints:
BEEP BOOP
- string to number:
Number('123') === 123
- number to string:
(123).toString() === '123'
- number to binary string: `(123).toString(2) === '1111011'
- number to hex string: `(123).toString(16) === '7b'
- binary string to number:
parseInt('1111011',2) === 123
- hex string to number:
parseInt('7b',16) === 123
turn (most) any object into a string:
var obj = [ 1, 2, 'xy', { z: 3 } ];
var str = JSON.stringify(obj);
console.log(str);
prints:
[1,2,"xy",{"z":3}]
turn stringified json back into an object:
var obj = JSON.parse('[1,2,"xy",{"z":3}]');
console.log(obj);
prints:
[ 1, 2, 'xy', { z: 3 } ]
Split a string into an array of strings at a delimiter with
.split()
:
var str = 'abc:def:h:ij:klmnop'
console.log(str.split(':'));
prints:
[ 'abc', 'def', 'h', 'ij', 'klmnop' ]
Math.pow(base, exp)
- exponentiationMath.log(n)
- natural log (base e)Math.exp(n)
- e raised to the power nMath.PI
Math.E
Math.sin(x)
- sine of x in radiansMath.cos(x)
- cosine of x in radians
log base 2 of 255 = Math.log(255) / Math.log(2)
// create a new date instance (now)
var d1 = new Date
// date from milliseconds
var d2 = new Date(1420821045321)
// date from a string
var d3 = new Date('2015-01-04 15:00')
// number of milliseconds since 1970-01-01:
var now = Date.now()
var d = new Date
console.log(d.toString())
// 'Fri Jan 09 2015 10:18:26 GMT-0800 (PST)'
console.log(d.toISOString())
// '2015-01-09T18:18:26.194Z'
console.log(d.valueOf())
// 1420827506194
console.log([ d.getFullYear(), d.getMonth(), d.getDay() ])
// [ 2015, 0, 5 ]
console.log([ d.getHours(), d.getMinutes(), d.getSeconds() ])
// [ 10, 18, 26 ]
Your entirely optional homework is to get through the
javascripting
lesson on nodeschool:
http://nodeschool.io/#javascripting