Skip to content

Language 01

History

  • First version written by Brendan Eich, May 1995. In 10 days.
  • June 1997 ECMAScript 1 standard (European Computer Manufacturers Association)
  • June 1998 ECMAScript 2
  • December 1999 ECMAScript 3
  • Microsoft doing their own thing (JScript), ECMAScript 4 was never released. Browser wars.
  • December 2009 – ECMAScript 5
  • June 2015 – ECMAScript 2015 – ES6
  • June 2016 – ECMAScript 2016 – ES7
  • June 2017 – ECMAScript 2017 – ES8
  • June 2018 – ECMAScript 2018 – ES9
  • June 2019 – ECMAScript 2019 – ES10
  • ESNext – whatever is currently in Stage 4.
    Stages 1–3 are an incubator of new features, and features reaching Stage 4 are finalized as part of the new standard

What is really supported in browsers?

  • Browsers pick and choose what features to support
  • Use JS transpilers (Babel) – ES5 (and ES6) is fully supported in all modern browsers
  • Use TypeScript!!!
  • Use polyfills where needed

Strict mode

ES5 introduced Strict mode.
Eliminates some JavaScript silent errors by changing them to throw errors.
Fixes mistakes that make it difficult for JavaScript engines to perform optimizations: strict mode code can sometimes be made to run faster than identical code that's not strict mode.
Prohibits some syntax likely to be defined in future versions of ECMAScript.

1
2
"use strict";
x = 3.14;

Error - x is not declared

ALWAYS USE STRICT MODE!!!!!

Type system

JS is weakly and dynamicaly typed!

Types

  • Certain types as implicitly cast depending on the operation used. Inconsistently!
  • When adding a number to a string, the number will be cast to a string before performing concatenation, but when subtracting a number from a string, the string is cast to a number before performing subtraction.
  • Type is associated with value (not with variable)!

Value vs Reference

Primitive types (value) - Boolean, String, Number, null, undefined
Objects (reference) - Array, Function, Object

Variables

Modern way:

1
2
3
4
let x = 5;          // number
const y = foobar; // constant, can’t change
let z;              // undefined
let z = undefined;  // undefined
  • The name must contain only letters, digits, or the symbols $ and _.
  • The first character must not be a digit.
  • JS is case sensitive. Camelcase (camelCaseIsThis, ThisIsPascalCase, this_is_snake_case) is default.

Don’t use var! Don’t use "foobar = 5;" Constant naming – UPPERCASE for hardcoded values.

Datatypes - primitives

  • 7 primitive types

    • string
    • number
    • boolean
    • symbol
    • null
    • undefined
    • In some of the latest implementations - bigint
  • Objects

    • Is capable of storing multiple values as properties.
    • Can be created with {}, for instance: {name: "John", age: 30}.
      There are other kinds of objects in JavaScript: functions, for example, are objects.

Datatypes – primitives/object

There are many things one would want to do with a primitive like a string or a number. It would be great to access them as methods.
But - primitives must be as fast and lightweight as possible (objects are slow).

  • The language allows access to methods and properties of strings, numbers, booleans and symbols.
  • In order for that to work, a special “object wrapper” that provides the extra functionality is created, and then is destroyed.
  • The “object wrappers” are different for each primitive type and are called: String, Number, Boolean and Symbol.
  • null/undefined have no wrappers/methods

Constructors String/Number/Boolean are for internal use only!

  • Possible for historical reasons, but highly unrecommended
  • Unexpected results in various use cases
    • alert( typeof 0 ); // "number"
    • alert( typeof new Number(0) ); // "object"!

Using the same functions String/Number/Boolean without new is OK!

  • Convert a value to the corresponding type
    • Number("123") - 123

Datatypes - Number

  • Float, int – number
  • Special numeric values: Infinity, -Infinty, NaN
    • NaN – Not an Number
  • Math operations are safe – no crashes (NaN is returned)
  • Max value is 2^53 (-2^53 for negatives) – ca 16 decimal digits
  • Stored as 64bit, double precision floating point numbers (IEEE-754)
  • Big or small numbers (with many zeroes)

    • let billion = 1e9 (1000000000)
      • 1 and 9 zeroes
    • let microsecond = 1e-6
      • (0.000001) - six zeroes to the left from 1
  • Hex

    • 0xff, 0xFF – case does not matter
  • Binary
    • 0b11111111 - 255
  • Octal
    • 0o37 – 255

So four numerical bases are directly supported – binary, octal, decimal (default), hex

  • numericvariable.toString(base) – return string representation of value, using base (default – 10, max 36)
  • Calling it directly on number
    • 123456..toString(36) – notice two dots. Single dot is decimal separator.
    • (123456).toString(36)

Rounding

Math.floor, Math.ceil, Math.round, Math.trunc

Types

numericvariable.toFixed(decimalPlaces) – returns string, rounds, decimals padded right with zeroes to get required length.

1
12.345.toFixed(5)  12.34500

isFinite and isNaN

  • isNaN(value) converts its argument to a number and then tests it for being NaN
  • isFinite(value) converts its argument to a number and returns true if it’s a regular number, not NaN/Infinity/-Infinity
Danger

The value NaN is unique in that it does not equal anything, including itself – you have to use isNaN function

Parsing

  • parseInt(string [, radix])and parseFloat(string [, radix])
    • Converts the string to a number (until possible) and returns resulting number.
    • parseInt('100px’) – 100
    • parseFloat('12.5em’) – 12.5
    • parseInt('a123’) – NaN

Math fn

Other Math functions
- Math.max(a, b, c...) / Math.min(a, b, c...) - Math.random() – 0..<1 - Math.pow(n, power) - Math.abs()

Don’t forget, that underlaying data type is 64bit float

  • 1.35.toFixed(1) – 1.4, 1.35.toFixed(20) - 1.35000000000000008882
  • 6.35.toFixed(1) – 6.3, 6.35.toFixed(20) - 6.34999999999999964473

Datatypes - String

Surrounded by quotes.
3 types of quotes are in use.

  • Double quotes: "Hello".
  • Single quotes: 'Hello'.
  • Backticks: `Hello`.

Backticks are “extended functionality” quotes - allow to embed variables and expressions into a string by wrapping them in ${…}

1
alert( `the result is ${1 + 2}` );

No character type!

Backticks allow a string to span multiple lines

1
2
3
4
5
let guestList = `Guests:
* John
* Pete
* Mary
`;

Special characters

Types

The length property has the string length
To get a character at position pos, use square brackets [pos] or call the method str.charAt(pos).
The first character starts from the zero position

Difference between them is that if no character is found, [] returns undefined, and charAt returns an empty string

Iterate over string chars

1
for (let char of "Hello") {  }

Strings are immutable!

  • str.indexOf(substr, pos)
    It looks for the substr in str, starting from the given position pos, and returns the position where the match was found or -1 if nothing can be found.

  • str.lastIndexOf(substr, position)
    searches from the end of a string to its beginning.

  • str.includes(substr, pos) returns true/false depending on whether str contains substr within.

  • str.startsWith and str.endsWith
    do exactly what they say

  • str.slice(start [, end])
    Returns the part of the string from start to (but not including) end. Negative values for start/end are also possible - position is counted from the string end

  • str.substring(start [, end])
    Returns the part of the string between start and end.
    This is almost the same as slice, but it allows start to be greater than end.

  • str.substr(start [, length])
    Returns the part of the string from start, with the given length.

Strings are compared character-by-character in alphabetical order.

1
'a' > 'Z' // true
  • str.codePointAt(pos)
  • String.fromCodePoint(code)

Correct string comparison:
referenceStr.localeCompare(compareString[, locales[, options]])

  • https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/localeCompare

Datatypes - Boolean

  • Only two values
    • true
    • false

Datatypes - null

  • Special type. Only one value
    • null
  • Has no special meaning.

Datatypes - undefined

  • Special type, only on value
    • undefined

The meaning of undefined is “value is not assigned”.
If a variable is declared, but not assigned, then its value is undefined

1
2
let x; 
alert(x); // shows "undefined”

It’s possible to assign undefined to variable.
Not recommended, use null instead.

Datatypes – Object and Symbol

  • Objects are used to store collections of data and more complex entities.
  • The symbol type is used to create unique identifiers for objects.

We will look at them more deeply soon…

typeof operator

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
typeof x // returns string
typeof(x) 

typeof undefined // "undefined"
typeof 0 // "number"
typeof 10n // "bigint"
typeof true // "boolean"
typeof "foo" // "string"
typeof Symbol("id") // "symbol"
typeof Math // "object"  - Math is built-in object 
typeof null // "object"  - official error in typeof, kept for compatibility
typeof alert // "function"  - actually object, but typeof treats them differently. Not correct, but useful.

Summary of types

  • 7+1 basic types

    • number for numbers of any kind: integer or floating-point, integers are limited by ±2^53.
    • string for strings. A string may have one or more characters, there’s no separate single-character type.
    • boolean for true/false.
    • null for unknown values – a standalone type that has a single value null.
    • undefined for unassigned values – a standalone type that has a single value undefined.
    • object for more complex data structures.
    • symbol for unique identifiers.
    • bigint is for integer numbers of arbitrary length.
  • The typeof operator allows us to see which type is stored in a variable.

    • Two forms: typeof x or typeof(x).
    • Returns a string with the name of the type.
    • typeof null returns "object" – this is an error in the language, it’s not actually an object.

Array

Arrays are list-like objects whose prototype has methods to perform traversal and mutation operations.
Neither the length of a JavaScript array nor the types of its elements are fixed.

1
2
3
let arr = new Array(); 
let arr = []; 
let fruits = ["Apple", "Orange", "Plum"];
  • 0 indexed
1
alert( fruits[0] ); // Apple
  • pop() push()
  • length

Most importan array function

  • splice(fromIndex, elementCountToDelete)
  • splice(fromIndex, elementCountToDelete, newElementsToInsert)

Iterate over array

1
for (let fruit of fruits) {}

No multidimensional arrays.

Jagged OK.

1
2
3
4
5
someArray.length = 5; // set length (truncate elements)

let arr=[];
// misuse
arr[5] = "foo";
  • https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array

Type Conversions (primitives)

String conversion happens when we need the string form of a value.
String conversion is mostly obvious.
A false becomes "false", null becomes "null”

Numeric conversion happens in mathematical functions and expressions automatically.

1
"6" / "3" //2
  • undefined – NaN
  • null – 0
  • true - 1
  • false – 0
  • string – trimmed first
  • empty string - 0

Type Conversions (primitives) - Boolean

Values that are "empty", like 0, an empty string, null, undefined, and NaN, become false.
Everything else is true (any non empty string, objects, [], {}, negative numbers)

  • Boolean("") – false
  • Boolean("0") – true
  • Boolean(" ") – true

This conversion or principle is called Truthy-Falsy

Operators – equality, non-equality

Equality and non-equality
== and !=

But, they will try convert values to same type

1
1 == "1" // true

Type and value equality – strict equality === and !==

1
1 === "1" // false

Operators - unary

  • --var; ++var; // variable gets incremented and then used (prefix)
  • var--; var++; // variable gets used and the incremented (postfix)
  • +var; //convert string to number – does not change sign
  • -var; // changes sign of number

Operators - logical

Typical C – && - and, || - or, ! – boolean not

1
let x = predicate ? Truevalue : falsevalue;

Careful with operator priority – && - and has higher precedence

1
2
3
4
5
if (firstRun == true || selectedCategory != undefined && selectedState != undefined) {}
if (firstRun == true || (selectedCategory != undefined && selectedState != undefined)) {}
if ((firstRun == true || selectedCategory != undefined) && selectedState != undefined) {}

if (firstRun == true) || ((selectedCategory != undefined) && (selectedState != undefined)){}

Generally

  • Grouping: ()
  • Member access . or [...]
  • Not: !
  • Comparison, e.g. < , >= , === , !=, ...
  • Logical AND && (its multiplication 0 * 1 = 0 => FALSE)
  • Logical OR || (its adding 0 + 1 = 1 => TRUE)

MDN

Common use outside if

1
settings = userSettings || defaultSettings;

If userSettings is falsy, then defaultSettings is asigned to settings.

Operators - relational

Classical

  • > < <= >=
  • Careful with string comparison! "Z" < "z"

Operators - assignmnet

  • =
  • += -= /= *= %=

Advanced bitwise logic

  • var1 << 1; // shift 1 bit to left
  • var1 >> 1; // shift 1 bit to right, keep sign
  • var1 >>> 1; // shift 1 bit to right, zero fill
  • & - and, | - or, ^ - xor, ~ - not,

Operators - ?? ?.

  • ?? and ?. – same as in C#
  • ?? - nullish coalescing operator
  • ?. - optional chaining operator
    (experimental, Chrome 79. Supported in TS)

Nullish – null or undefined