JavaScript Intro
JavaScript is both the most popular and least popular programming language.
– Doug Crockford
JavaScript is the language of the web. It runs in every web browser, has influenced a standard way of communicating data between computers, and has even broken into the backend scene with technologies like node.js and Meteor. Since just about every computing device can connect to the web and run JavaScript, in many ways JavaScript is the most “popular” language.
By that same token, there are a lot of intricacies and pitfalls that make JavaScript unique. It’s these sorts of non-intuitive quirks that make it difficult to use correctly. While JavaScript is very powerful, most people who work in it regularly don’t like the way it was designed.
The next few sections of this guide will introduce you to the language’s features and paradigms, and point you towards resources for further learning.
Overview of JavaScript
JavaScript is as a programming language shares many features with other popular programming languages that you may have encountered, such as Java, C & C++, and Python. It’s important to note at this point that JavaScript is not Java. The fact that they share a name was a marketing ploy when JavaScript was first released to increase it’s popularity. Even though the two languages look similar, the underlying languages are completely different.
As much as I’m going to try in this workshop, it’s impossible to learn to program effectively in only a few hours. With this in mind, it’s expected that you have had some sort of programming experience for you to get the fullest out of this workshop. The aim of this workshop will be to introduce the syntax and semantics of the language, with the ultimate goal of building a couple frontend web apps. On that note, let’s dive right in!
Syntax Crash Course
Variables & Objects
Variables in JavaScript are similar to variables in Python, and different from
those in C++ or Java. The biggest difference is that you don’t declare the type
of a variable. In Java or C++ you have to decide what type of variable to use
when you create the variable. For example, you might have to declare a varible
to be an int
or a string
. However, Javascript works like python: you can
assign whatever value to a variable, and it’s type will be resolved at runtime.
Here are some examples:
var foo = 3.14;
var bar = "thon"
var baz = true;
As you can see from the examples, the var
keyword is used to indicate that a
particular identifier (like foo
, bar
, or baz
) is meant to be used as a
variable. We use the var
keyword regardless of the type of value we assign to
the variable.
Types
As you can see from the previous example, there are a number of types which are already baked into JavaScript. The following is a “complete” list of JavaScript types:
number
This includes all number types: integers, floating point decimal numbers,
and two special types of “numbers” which are NaN
for “not a number” and
Infinity
. Their use is minimal in most programs, but it’s still
interesting to know that they exist.
Important takeaway
JavaScript makes no difference between integers and floating point numbers. This is different from probably all languages you have experienced previously.
string
This includes any number of characters in a row. There is no type that represents a single character: “a” and ‘a’ are both strings of length 1.
Important takeaway
JavaScript has support for strings built into the language.
boolean
The boolean type is very similar to all other languages. Note that in JavaScript, every value is “truthy”, meaning that trying to convert any JavaScript value to a boolean is always well defined.
Important takeaway
A boolean value can be either
true
orfalse
.
object
JavaScript is object-oriented, though not in the way you might expect if you’re similar with Java or Python. Unlike the others, JavaScript uses “prototypical inheritance” instead of class-based inheritance. JavaScript objects are very powerful, but they’re a little harder to use and we’ll spend a lot of time explaining how to use them.
Important takeaway
JavaScript objects are super nifty, though using them for inheritance is nothing like what you’d expect from other languages.
function
In JavaScript, functions are values! This is actually really cool, and if you’ve ever taken a class about functional programming (like 15-150 at CMU) you know just how powerful functions can be. For those who haven’t, functions as values simply means you can store, return, and otherwise manipulate functions like any of the above types of values. JavaScript makes heavy use of this fact, and it’s one of the most expressive ways to handle asynchronous events, which we’ll discuss later.
Important takeaway
Functions are values, so you can manipulate them as if they were numbers, strings, booleans, or objects.
undefined
There is one last type: undefined. Undefined is both a value and a type, and it
is generally used only by the JavaScript language to indicate the quality of
an “absent” or “uninitialized” value. Note: JavaScript also has the null
keyword. The differences between null and undefined will be discussed below.
Important takeaway
undefined
is used to indicate that an expression was never assigned a value, whereasnull
is used for variables that are intentionally valueless.
Null vs Undefined
In JavaScript, the reserved words null
and undefined
both have a similar
use: to describe that the value of some expression doesn’t have a meaningful
value.
You might be wondering, wait, don’t “null” and “undefined” mean practically the
same thing? Why have both? For one thing, null
is actually of type "object"
while undefined
is it’s own type. But the reason for there being two
apparently identical keywords is that undefined
is used only by core language
features, whereas null
is reserved for use exclusively by developers like you
and me.
This aids in debugging: when you come across the value of some variable as being
null
, you can be sure that you personally set it to null. On the other hand,
if something has a value of undefined
, it’s generally an indication that
something with the core JavaScript language functionality is involved.
This distinction doesn’t necessarily help us get writing web apps more quickly, but it’s still an important point to bring up. This is one of the many intricacies of JavaScript, an idiom that you will likely come across or have an issue with at some point. Unfortunately, JavaScript is full of intricacies, and there’s no master list. That being said, this list by AirBnb comes pretty close to being exhaustive.
Truthiness
As mentioned earlier, every JavaScript value is either “truthy” or “falsy”.
What this means is that if you want, you can convert any JavaScript value into
a boolean. This conversion is done whenever you put a value inside a
conditional. This makes some code really hard to read and other code really
simple; it helps if you understand the following rules governing which values
are “truthy” (or convert to true
), and which are “falsy” (meaning they are
equivalent to false
):
falsy | truthy | |
---|---|---|
number | +0 , -0 , NaN |
all other numbers |
string | "" |
all other strings |
boolean | false |
true |
object | null |
all other objects |
function | n/a | all functions |
undefined | undefined |
n/a |
Objects
We’ve been hinting at what objects are in the previous discussion, but as of yet, we’ve not introduced any concrete example of what an object in JavaScript is. Objects in JavaScript are incredibly powerful because they’re actually just mappings (like a hash table or dict) where key-value pairs are stored.
Here is an example of an object:
{
foo: 3.14,
bar: "thon"
}
As you can see, an object is indicated by putting keys, followed by a colon,
followed by expressions or values, between curly braces and separating them with
commas. In the above example, “foo” and “bar” are identifiers, and 3.14
and "thon"
are values. Since objects are values, we can store this in a variable:
var myFirstObject = {
foo: 3.14,
bar: "thon"
};
and then access the properties (or keys) of that object using one of two ways:
myFirstObject.foo === 3.14 // true
myFirstObject["foo"] === 3.14 // true
myFirstObject.foo === 0 // false
// These have the value "thon"
myFirstObject.bar === "thon" // true
myFirstObject["bar"] === "thon" // true
myFirstObject["bar"] === "hacka" // false
In addition to noticing that you can use both the dot (.
) and subscript ([]
)
operator to access an object’s properties, you probably also noticed that we use
//
for comments, and ===
for equality comparisons. This is another one of
JavaScript’s quirks: using ==
is also sometimes valid, but it does weird
things with conversion which we’ll actually talk about next!
Operators & Conversion
The operators you’ll find in JavaScript are pretty much the same as in any other language. Here are a bunch: if you don’t think you know what one of these symbols means, look up JavaScript operators to learn more:
+ - / * ++ -- ! ~ % << >> & | == === != !=== < > <= >= && || ?: = ,
In addition to these symbols, JavaScript has a few of it’s own reserved words that function as operators:
typeof
returns the type of a value:
> typeof(3.14)
'number'
> typeof("thon")
'string'
delete
removes a property from an object:
> delete myFirstObject.foo;
> myFirstObject
{ bar: 'thon' }
Caveat about delete
: in JavaScript, arrays are actually just objects
where the keys are zero-indexed numbers (with a few special properties). This
means that we can use delete
on arrays to delete individual elements, but
it’s oftentimes not what you want.
in
tells you whether a given property is in an object
> bar in myFirstObject;
true
Caveat about in
: this operator will look for properties anywhere in the
object’s prototype. This means, for instance, that ’toString’ in {}
returns
true
, because the function toString
is a property of all objects through
the default prototype. Prototypes are discussed in more detail below.
We can also convert types between different values. This will happen whenever we try to use an operator between two values that have different types. As an example:
> "ab" + 3
'ab3'
Note that here, because we had a string and a number, the final conversion was to a string. Implicit conversion is highly irregular though, so you should always explicitly convert between types when you need to.
Functions
There are more or less three ways of declaring functions in JavaScript: two of them assign a name to the function, and the last way leaves the function “anonymous”, or nameless.
// First named method: `function` keyword followed by identifier, (), and {}
function myFirstFunction() {
...
}
// Anonymous method: omit identifier
function () {
...
}
// Second named method: assign anonymous method to a variable
var myFirstFunction = function() {
...
}
// Third named method: sane scoping & named function in stack traces
var myFirstFunction = function myFirstFunction() {
…
}
In this example, the anonymous method is so lonely! That’s because normally when you have an anonymous method, you are passing it directly into another function, or declaring it and calling it at the same time. In both of these cases, you don’t need to give the function a name for it to be useful.
Function arguments are specified like in Python, but the keyword function
is used instead of def
:
function mySecondFunction(arg1, arg2, anotherArg) {
...
// use arg1, arg2, and arg3 variables
...
}
Hoisting
Hoisting is another one of those JavaScript idiosyncrasies I keep talking about,
and it deals with how and when variables are defined. Put overly simply,
whenever JavaScript encounters a variable declaration at any point within a
scope, it hoists the variable declaration to the top of the scope, settings
its value to undefined
. This can cause problems if you run into situations
where the scope is complex, for example when using closures.
Because hoisting has been widely discussed elsewhere already, I’m simply going to leave this link here and let people read it. For the purposes of this workshop, it shouldn’t ever become an issue. However, hoisting is something about JavaScript that all proficient web developers should have some grasp of.
Constructors & Prototypical Inheritance
Alright, we’re in the home stretch! This is the last section before we dive into the much more exciting world of web app development. Hang in there!
JavaScript supports the programming paradigm known as Object-Oriented
Programming. This means that we need a way of constructing objects, something
which in C++ or Java is done with the new
keyword, and which in Python is done
using simply the name of a class with the assignment operator.
In JavaScript, there is no concept of “classes”. Instead, to create a constructor, we simply declare a function:
function Person(name, age) {
this.name = name;
this.age = age;
}
We use the this
keyword to indicate that a particular property (like “name” or
“age”) should be stored on the object that we are constructing.
To invoke our constructor, we call this function after the new
operator:
var person1 = new Person("Jake", 19);
We can also manipulate an object’s
prototype. An object’s prototype is a sort of reserved area on an object where
JavaScript will check for a property if one isn’t defined on the object
normally. For example, we can attach an introduce
property to Person
’s
prototype, and it will then be available on all subsequent Person
objects:
function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype.introduce = function() {
console.log("Hello, world! My name is " + this.name + " and I am " + this.age + " years old.");
}
Notice that console.log
is just the way of printing a value to the console in
JavaScript, which can be seen by pressing Command + Option + J on a Mac or
Ctrl + Shift + J on a PC (assuming that you’re using Chrome).
Now, whenever we instantiate a Person, the introduce method will be available:
function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype.introduce = function() {
console.log("Hello, world! My name is " + this.name + " and I am " + this.age + " years old.");
}
var person1 = new Person("Jake", 19);
var person2 = {
name: "Jake",
age: 19
}
person1.introduce(); // 'Hi! My name is Jake and I am 19 years old.'
person2.introduce(); // TypeError: Object has no method 'introduce'
Manipulation of prototypes is also involved in inheritance and the instanceof
keyword, which are both powerful techniques, but something that would take too
much time to introduce here. We’ve got web apps to write!
For the lab portion of this session, visit this page.
Written by Jake Zimmerman, July 2014