Introduction to JavaScript for Python Users

Python and JavaScript are actually quite similar languages. One major similarity is that they are both interpreted languages, in that when the code is run, each statement is checked one at a time and executed in this fashion. This is different from a compiled language, where the code is checked all at once by the compiler before it is run. CS 230 teaches Java, which is a compiled language.

Think of translation of spoken languages: There are people who translate speech on the fly while it's being spoken. There are also people who will read an entire script beforehand, translate it in one sitting, then give the entire translated speech at once. Computer science-wise, the person who translates on the fly is like an interpreted language, while the person who translates in one sitting is like a compiled language.

On another note, you may think that JavaScript is similar to Java due to their names, but make no mistake! They are extremely different in functionality, and the name JavaScript was only given in an attempt to boost its popularity (as Java was quite popular at the time). The official name of JavaScript is actually ECMAscript, but we will continue to refer to it as JavaScript.

In this reading, we'll be highlighting some important differences between JavaScript and Python.

Syntactic Differences

Python:

def helloWorld():
    print("Hello world!")
    print("I like CS 204")

JavaScript:

function helloWorld() {
    // Similar to Python's print, but console.log is most often 
    // used in the browser rather than an environment like Canopy
    console.log("Hello world!"); 
    console.log("I like CS 204");
}

JavaScript uses curly braces to indicate code blocks, while Python uses indentation. Also, Javascript uses semicolons to terminate statements, while python uses newlines.

Technically speaking, the following code is acceptable and does the same thing:

function helloWorld(){console.log("Hello world!");console.log("I like CS 204");}

(In fact, sometimes JavaScript is minified before sending it to the browser, where all unnecessary characters are removed to speed up network transmission. But for readability, (as there will be humans reading your code, not just machines!) it's important to indent properly.)

Type

Values in JavaScript can be one of the following types. You can click through to find out more technical details. (There are other types as well; this list is not exhaustive.) But we will see all of these this semester.

  • null: The null object is similar to Python's None object. We won't worry about it a lot, but it will come up sometimes.
  • undefined: A variable that is not assigned a value has the value "undefined", which is different from null. You should almost always give a variable a value, but it's not required.
    
    var question = "What is the meaning of life?";
    var answer;  // value is undefined
    
  • Number: Numbers are straightforward. Examples like 7 or 3.14 are simple numeric literals. Python distinguishes integers from floating points values, but JavaScript doesn't typically distinguish them.
    
    var radius = 10;                             // an integer
    var area = 3.14 * radius * radius;           // floating point values
    var area_better = Math.pi * radius * radius; // use a pre-defined constant
    
  • String: A string is a sequence of characters enclosed by quotation marks, either single quotes or double quotes (but they much match). There is no multi-line string like Python's triple-quoted strings. You may not break a string literal across a line boundary. The typical work-around is to use string concatenation like this:
    
    var quote = 'Now is winter of our discontent' +
                "Made glorious summer by this son of York";
    
  • Boolean: There are two literal values for true and false: true and false. Unlike Python, these are not capitalized.
  • Object: In JavaScript, objects play two roles. First, they are simple data structures of key/value pairs, virtually identical with Python's dictionaries. Second, they can also contain methods and become the essential building blocks of object-oriented programming, which we will discuss later this semester.
  • Function: Functions are standard in any programming language. In JavaScript, as in Python, functions are first class objects, which means that they are a kind of data, meaning that they can be stored in variables, returned from functions, passed into functions as arguments, and stored in data structures. Front-end web development makes extensive use of that feature, so we'll see it a lot this semester.
  • Array: Like Python, JavaScript has arrays. They are created with square brackets and commas, just as in Python. JavaScript doesn't have some of the same notations such as negative arguments to count from the end or getting slices by using colon notation.
    
    var primes = [2, 3, 5, 7, 11];
    
  • Date: A date object represents a moment in time (to the nearest millisecond). JavaScript has a built-in way to create date objects and to operate upon them. We'll discuss them next time, and we'll use them in at least one assignment and in the project.
    
    var roger_wins_aus_open = new Date('29 Jan 2017 7:14 am'); // EST
    

    Internally, times are represented in Universal Coordinated Time (UTC) which is essentially Greenwich Mean Time, though you can typically work in local time. We won't be discussing timezones and such in this course; time is a complicated thing.

Variable Declaration

Python:

animal = "cat"

JavaScript

var animal = "cat";

When you use var, you are declaring a new variable. Without var, you are referencing a previous variable.

In general, JavaScript variables act quite similarly to Python variables, except for scope. In a Python function, a variable is local unless you make it global. In a JavaScript function, a variable is global unless you make it local by using var.

Inside a function, you should always use var unless you intend to reference a global variable.

Conditionals

In Python, indentation is crucial to conditionals. In JavaScript, we use braces to demark the beginning and end of blocks of code, and indentation just as helpful information to the reader.

Python:


# Python conditionals

if age >= 18:
    print "You can vote"

    if age >= 21 or (age >=18 and !currentlyInUS):
        print "You can get a drink"
elif age >= 16:
    print "You can get your license"
elif age == 15:
    print "You can get your permit"
else:
    print "No special privileges yet"

JavaScript:

// JS conditionals. Notice the logical expressions in
// parentheses, such as (age >= 18)

if (age >= 18) {
    console.log("You can vote");

    if (age >= 21 || (age >= 18 && !currentlyInUS)) {
        console.log("You can get a drink");
    }
} else if (age >= 16) {
    console.log("You can get your license");
} else if (age == 15) {
    console.log("You can get your permit");
} else {
    console.log("No special privileges yet");
}

Here's a quick summary of the differences for condionals and booleans:

Python: and or elif True False if True:
# Do something
JavaScript: && || else if true false if (true) {
// Do something
}

Functions

As you've seen earlier, JavaScript functions differ as it uses the key word function instead of def.

function name(parameter1, parameter2, parameter3) {
    return value
}

Like in Python, JavaScript functions are first-class values, so they can be stored in variables, passed and returned as data, and so forth.

Unlike Python, JavaScript is very flexible about the arguments. Any extra arguments are ignored, and there is no error for missing arguments (though your code might not work properly).

function sub(a,b) {
    return a-b;
}

sub(5,4,3); // returns 1, the 3 is ignored
sub(5,4);   // returns 1
sub(5);     // the subtraction will yield NaN, for Not a Number

Invoking Functions

If a function is also a kind of data, how can you tell the difference between using a function as a function versus moving it around like data? The answer is the parentheses. When you invoke a function, you give it some inputs in paretheses, and that triggers the execution of the function.

The metaphor I like is that a function is a kind of machine. It takes inputs and produces outputs, somewhat like a food processor takes in chunks of food and outputs finely chopped food. The parentheses are like the go button on a food processor. Let's imagine our food processor takes a number as input and produces its square root:

def process(x) {
    return Math.sqrt(x);
}

var x = process(4);  // run the processor
var m = process;     // just copy the machine to another place, m
var y = m(9);        // run the copy on a different input

The last few lines are similar looking but the ones with parentheses are running the machine with a given input. Without the parentheses, we are just copying the machine from one variable (process) to another (m).

Anonymous Functions

Functions without the function names are called anonymous functions. In Python, you use lambda to create anonymous functions, but most versions of CS 111 don't cover lambda, so we'll omit lambda here. However, you may have seen lambda in the context of a key function for sorting, like this:

# python code
student_tuples = [
    ('john', 'A', 15),
    ('jane', 'B', 12),
    ('dave', 'B', 10)
]
sorted( student_tuples, key=lambda student: student[2]) # sort by age

To create an anonymous function in Javascript, simply use the keyword function without the function name. This syntax is called a function literal or a function expression, and so you would typically put it on the right hand side of an assignment (like other expressions) or put it in the parentheses of a function call. Here's an example:

// JavaScript code
var multiply = function (a, b) {return a * b};

// x is the returned value of 20
var x = multiply(4,5) 

We'll see how anonymous functions can be used in more practical applications later.

Built-in Functions

Here are some useful built-in functions and their JavaScript equivalent:

Python JavaScript Description
print(x) console.log(x) prints a value to the console
no equivalent alert(x) pops up a window displaying the value
input(str) prompt(str) Not an exact comparison, but the Python version gives a text prompt, while the JavaScript version gives a pop-up prompt in the browser.
len(a) a.length Returns length of a string or array
str(a) String(a) or a.toString() Converts type to string
max(a, b) Math.max(a, b) Returns maximum of two numbers
min(a, b) Math.min(a, b) Returns minimum of two numbers
random.randint(a, b) Math.random() Returns a random number. Python returns a random number from a to b inclusive, while Javascript returns a random number from 0 to 1. You can use write a function to specify what you need, as detailed in this documentation. You need to import the random library for Python, while JavaScript's Math object is already built-in.

String Concatenation

As with Python, you can concatenation two strings with the + operator. However, in JavaScript, the values don't have to be strings. If they aren't, they are converted to strings. So the following is quite common:

var ans = 3+4;
alert('the answer is '+ans);

The first + is actual addition; the second concatenates the string 'the answer is' with the value in ans (presumably 7), converting the 7 to a string, and pops up a window with the result.

Arrays

As we saw above, JavaScript arrays are very similar to Python arrays. They have a .length property that gives the length, similar to Python's len() function.

var primes = [2, 3, 5, 7, 11];
var pl = primes.length;  // 5
alert(pl+' primes');  // 5 primes

There are also methods to operate on each element of an array. For example, if I have a list of numbers, and I want a list of their squares, I can do this:

function square(x) {
    return x*x;
}

var nums = [1, 2, 3, 4];
var squares = nums.map(square); 
alert(squares);  // [1, 4, 9, 16]

The .map() method takes a function of one argument, applies it to each element in turn, and collects the results into a new array.

Here's the same code as above, but this time using an anonymous function instead of defining square:

var nums = [1, 2, 3, 4];
var squares = nums.map(function (x) { return x*x }); 
alert(squares); // [1, 4, 9, 16]

The nice thing about using the anonymous function literal as the argument to the .map() method is that all the code is right there; you don't have to look elsewhere for the function code.

A method similar to .map is forEach(), which takes a function of three arguments: the item, its index in the array, and the array itself. In practice, the third argument is often ignored. The following prints out the contents of an array, using an anonymous function, and ignoring the third argument.

var primes = [2, 3, 5, 7, 11];
primes.forEach(function (item, index) {
     console.log(index+': '+item);
});

Sorting

Sorting in JavaScript is not quite as easy as it is in Python. We will re-visit it a few times this semester, but let's start with sorting numbers and strings.

Unsurprisingly, strings are sorted in dictionary order, a-z:

words = ['ball','ape','bay','apple'];
words.sort();
console.log(words);
[ 'ape', 'apple', 'ball', 'bay' ]

If you want reverse order, you could sort and then reverse:

words = ['ball','ape','bay','apple'];
words.sort();
words.reverse();
console.log(words);
[ 'bay', 'ball', 'apple', 'ape' ]

But uppercase and lowercase letters don't overlap, so you might not be happy with the following result:

words = ['ball','ape','Boston','Akron'];
words.sort();
console.log(words);
[ 'Akron', 'Boston', 'ape', 'ball' ];

If you want to keep the words the same, but sort them as if they were all the same case, one option is to use a comparison function.

Sorting with a Comparison Function

Almost all sorting algorithms in Computer Science are based on pairwise comparison of elements. Any pairwise comparison between two elements, a and b, has three possible outcomes: a<b, a==b, and a>b. The convention in many sorting algorithms is that the comparision function will be invoked on a pair of elements and it has three kinds of return values:

  • negative if a<b
  • zero if a==b
  • positive if a>b

That is, if the comparison function returns any negative value, the algorithm will ensure that a comes before b in the sorted array.

The comparison function is supplied as an optional argument to the .sort() method.

Here's one way we could sort strings ignoring case:

function cmp(a,b) {
    var aup = a.toUpperCase();
    var bup = b.toUpperCase();
    if( aup < bup ) {
        return -1;
    } else if ( aup == bup ) {
        return 0;
    } else {
        return 1;
    }
}
words = ['ball','ape','Boston','Akron'];
words.sort(cmp);
console.log(words);
[ 'Akron', 'ape', 'ball', 'Boston' ]

That works, but it's cumbersome. It turns out that there is a built-in string method that compares two strings and returns negative/zero/positive as desired. The name is localeCompare(); the name has locale in it because the method has some features to compare strings in language-specific ways. We might get into this later, but for now we will ignore non-English strings. Thus, we have:

function cmp(a,b) {
    var aup = a.toUpperCase();
    var bup = b.toUpperCase();
    return aup.localeCompare(bup);
}
words = ['ball','ape','Boston','Akron'];
words.sort(cmp);
console.log(words);
[ 'Akron', 'ape', 'ball', 'Boston' ]

Sorting Arrays of Numbers

Sorting numbers is surprising:

nums = [1, 3, 2, 11, 33, 22];
nums.sort();
console.log(nums);              
[ 1, 11, 2, 22, 3, 33 ]

The reason for this odd result is that the numbers are being sorted as strings. To sort them as numbers, we can again use a comparison function. Since the comparison function needs to return negative if a should come before b, one easy way to do that is to subtract. Here are some examples:

function sub(a,b) {
   return a-b;              
}
[1,2].sort(sub);
[2,1].sort(sub);
nums = [1, 3, 2, 11, 33, 22];
nums.sort(sub);
console.log(nums);
[ 1, 2, 3, 11, 22, 33 ]

Gotchas!

An important fact is that you can add numbers and strings together in JavaScript, which is unlike Python. Javascript turns the number into a string, concatenates the two together, and returns the resulting string.

var notFour = 2 + "2" // Gets "22"
var ourClass = "CS" + 204 // Gets  "CS204"
var piString = 3.14 + "1519" // Gets "3.141519"

But the pitfall is that if you're not careful, you can get results you didn't expect:

var x = prompt('first value to add');
var y = prompt('second value to add');
var z = x + y;
alert('result is '+z);

If you want to change your string into a number, there are the functions parseInt() and parseFloat()

three = parseInt("3.14") // Gets 3
pi = parseFloat("3.14") // Gets 3.14

Thus, the earlier example can be corrected to:

var x = parseFloat(prompt('first value to add'));
var y = parseFloat(prompt('second value to add'));
var z = x + y;
alert('result is '+z);

Optional Additional Information

You can omit reading the following. It's optional.

let statements

Newer versions of JavaScript support let as well as var. They are similar, but not identical. They differ slightly in scope:

  • var makes a variable available throughout a function
  • let limits a variable to the current "block" (essentially, a chunk of statements surrounded by braces).

If the difference matters, you are probably doing something subtle and sophisticated.

Arrow Functions

A relatively new feature of JavaScript is the ability to define arrow functions, which are even more succinct but also have some technical differences that we'll get into later. Arrow functions can only be one expression, which is returned.

primes = [2, 3, 5, 7 ];
prime_squares = primes.map( x => x*x );
alert(prime_squares); // [ 4, 9, 25, 49 ]
neg_primes = primes.map( x => -1*x );
alert(neg_primes);  // [ -2, -3, -5, -7 ]