preamble¶
in this notebook, we will very briefly cover some features of the language
for a more thorough study, refer to this excellent tutorial on javascript.info
as we go, we will point at a selection of chapters in that tuto
students interested should probably read it through
also remember that we focus on the browser runtime here
refer to this screenshot to spot the browser console
console.log() function¶
a function to show output - quite similar to Python’s
print()functionaccepts any number of arguments
of course from a browser it ends up in the devel tools area (under
nodeit will just print)
console.log(1, "two", [3, "four"])1 two [ 3, "four" ]
see also below how to format strings with backticks a la Python f-strings
syntax¶
the syntax is similar to C, C++ and Java
unlike Python, indentation does not matter
;is commonly used at the end of each statement (although this is not mandatory)[1]2 styles of comments
// this is a comment, no need to close // but must be repeated on each line // you may end all statements with a ; let a = 10; // but that's not mandatory let b = a * a /* this is another comment everything including newlines is ignored until the matching */
tests and loops¶
ifandwhilestatements are similar to C// conditional if if (a == 10) { console.log("YES", a) } else if (a == 12) { // } else { // }YES 10while (a >= 5) { console.log(a) a -= 3 }1074
== vs ===¶
talking of tests, a common pitfall for newcomers is the difference between == and ===[2]
==: loose equality, performs type coercion if needed===: strict equality, no type coercion
console.log( 10 == '10' ) // true - loose equality
console.log( 10 === '10' ) // false - strict equalitytrue
false
C-style for loop¶
C- or Java-like iteration loops are supported - although seldom needed
for (let i=0; i<2; i++) {
console.log(i)
}0
1
switch¶
the switch statement in JavaScript
is similar to the ones in C++ and Java
it will branch your control flow into a
location that depends on the subject’s value
do not forget the break statements !
switch (a) {
case 0:
console.log("ZERO")
break
case 10:
console.log("TEN")
break
case 20:
console.log("TWENTY")
break
default:
console.log("NONE")
}NONE
more on the switch statement
if the switch statement is new to you, please refer to this full article on javascript.info
variables¶
declaration¶
as usual, variables are names that refer to data in memory
like in Python, any such data is typed (although the name is not)
core language has some basic types
variables should be explicitly declared using one of the keywords
letorconst
let n = 10
console.log(typeof(n))
// possible since declared with let
n += 20number
30const s = "hello world"
typeof(s)
// we could not do this
// because declared with const
// s += ' john'"string"link in tuto
see more on this topic on javascript.info at this link https://
Python-style unpacking¶
// there is a form of parallel assignment
// similar to what Python offers
let [py, thon] = [10, 20]
console.log(py, thon)10 20
object unpacking¶
anticipating a bit, but there’s a very handy construction that looks a bit like the one above
// you receive some data from the outside
const data = {height: 100, width: 200, radius: 20, linewidth: 5}
// and you're interested in extracting width and height
// in two variables of the same name; easy !
const {height, width} = data
console.log(height, width)100 200
variable scope¶
like in all other languages, there is a need to limit the scope of a variable
so that variablexin 2 distinct functions do not clashJS uses lexical nested scope:
a variable is visible only within its code block (the stuff within{})
blocks {} and scope illustrated¶
the elementary unit for scope is the block - which is materialized by {}
let variable2 = "outermost"
{
let variable2 = "intermediate"
{
let variable2 = "innermost"
console.log("level 2", variable2)
}
console.log("level 1", variable2)
}
console.log("level 0", variable2)level 2 innermost
level 1 intermediate
level 0 outermost
do not use var !¶
(a lot of) legacy code uses the
varconstruct to declare variables - but this is dangerous !!JS being lax, it may accept a code where you don’t declare a variable at all
note that in this case you’re actually using a global variable - which is bad practice !bottom line: you should always declare your variables with
letorconst
globals¶
context (browser components mostly) is exposed to programer through a set of global variables, e.g.
window- the browser windowdocumentto access the DOM, remembergetElementById()consolelike inconsole.log()this- a tricky one
cannot inspect the browser globals from here
as it turns out, the code embedded in these notebooks is executed by an instance of node.js
for this reason so we could not inspect the document or window variables from right here
but of course you can do so from the browser’s console though
formatting with backticks¶
in JS, the backticks `` feature reminds of Python’s f-strings
let [x, y] = [100, 200]
// the `` is very similar to Python's f-strings
// except that you use ${expression}
// note the extra $ as compared to Python
console.log(`x = ${x} and x+y = ${x+y}`)x = 100 and x+y = 300
functions¶
like in other languages, and we have seen examples already
// the old way
function foo(x, y) {
console.log(`${x} + ${y} = ${x+y}`)
}
foo(10, 20)10 + 20 = 30
// a more fashionable way - similar to Python's lambdas
const bar = (x, y) => console.log(`from bar: ${x} + ${y} = ${x+y}`)
bar(100, 200)from bar: 100 + 200 = 300
// you can use { } if the code is more than one-line
// but make sure to explicitly use 'return' if you do !
const bar2 = (x, y) => {
let [x2, y2] = [x**2, y**2]
return x2+y2;
}
bar2(10, 20)500loose parameter binding¶
JavaScript is very permissive; for example, number of args is not checked
function fuzzy(x, y, z) {
console.log(`x = ${x} y = ${y} z = ${z}`)
}
fuzzy(10)
fuzzy(10, 20)
fuzzy("abc", "def", "ghi")
// and even this !
fuzzy("abc", "def", "ghi", "trashed")x = 10 y = undefined z = undefined
x = 10 y = 20 z = undefined
x = abc y = def z = ghi
x = abc y = def z = ghi
duck typing¶
like in Python, objects are typed, but variables are not bound to a given type
function foo(x, y) {
console.log('x is a ', typeof(x))
console.log(`${x} + ${y} = ${x+y}`)
}
// like in Python, function arguments are not statically typed
foo('abc', 'def')x is a string
abc + def = abcdef
this¶
a very specific feature of JS is that the implicit variable
thisis always definedthe content of
thisdepends on the contextuseful and relevant only for
methods (more on this later)
and some callbacks
// for example in this context, it's unclear what 'this' refers to
function show_this() {
console.log(typeof(this))
}
show_this()undefined
exceptions¶
JavaScript supports exceptions, just like Python, with the same bubbling mechanism
that scans the call stack until a catch statement is found
try {
// referring to an unknown variable
unknown
} catch (err) {
console.log(`OOPS name=${err.name}, message=${err.message}`)
}OOPS name=ReferenceError, message=unknown is not defined
classes¶
as of ES2015, the language has a proper class statement
class Vector {
// just like Python's __init__
// NO NEED to pass 'self' in JavaScript
constructor(x, y) {
this.x = x
this.y = y
}
// same for a regular method
display() {
console.log(`[Vector x=${this.x} y=${this.y}]`)
}
}
let vector = new Vector(10, 20)
vector.display()[Vector x=10 y=20]
old-school pseudo classes in JS before ES6
FYI, older JavaScript did not have a builtin class mechanism, and used other - quite cryptic - ways to create pseudo-classes
you may come across such older-school code that uses techniques typically involving a prototype thingy
but just stay away from that when you write new code, and just stick to the new idiom !
notes on classes¶
NOTICE the following facts from that first class example :
constructoris very much alike__init__in Pythonthe implicit
thisvariable refers to the current object
it is very much alike the traditionalselfargument in Python, except that it is not mentioned as a method parameterobjects get created with
new Vector()- Java and C++ style
and not just plain Python-styleVector()of course, inheritance is supported too; see
extendsandsuper()for details
get / set (advanced)¶
modern JavaScript has a native notion of what Python calls properties
i.e. expose an apparently mundane access to an instance attribute
through getter and setter functions
that intercept read/write attempts on the attribute
// get / set example
class Temperature {
constructor(temperature) {
this.kelvin = temperature
// "set kelvin(temperature)" will be called
}
get kelvin() {
return this._kelvin
}
set kelvin(temperature) {
if (temperature < 0) {
console.log("negative - refusing to set")
return
}
this._kelvin = temperature
// we must use the hidden variable this._kelvin
// that will store the value entered
// and will be returned when we ask for this.kelvin
// thanks to the get kevin() function
// if we had written this.kelvin = temp_value
// that would call set kelvin(temp_value) again
// and we would have an infinite loop
}
}let temp = new Temperature(10)temp.kelvin = -10negative - refusing to set
-10tempTemperature { _kelvin: 10 }