Introduction to JS

Always bet on JavaScript.

 

What is JavaScript?

A very short history

ECMAScript is the official name for JavaScript. A new name became necessary because there is a trademark on JavaScript (held originally by Sun, now by Oracle).

Created by Brendan Eich in the year 1995

It is said that Brendan Eich created the first version of the langauge in around 10 days.

JS is a dynamically-typed, interpreted (or JIT-compiled), multi-paradigm, prototype-based high level language.

Most Popular

Developer Roles

StackOverflow

2020 Dev Survey

Most Popular Technologies

Unsurprisingly, for the eighth year in a row, JavaScript has maintained it's stronghold as the most commonly used programming language.

What can you build with JS?

  • Rich and Interactive Web/Mobile apps
    • maps.google.com
    • facebook.com
    • Instagram app (earlier)
  • Desktop apps
    • Using React Proton / Electron
  • Real time networking apps
    • Google Meet
  • Command line tools
    • Using Node.js
  • Games
    • OnOff
  • anything you can imagine much more

Where can you execute JS?

  • In the browsers directly
    • Using the browser's console
    • Using third-party web apps such as codesandbox.io
  • In an HTML File (again using the browser)
    • Using <script> tag
  • In your PC
    • Using Node.js
  • IOT devices

JS (or ES) versions

  • Originally called LiveScript, by Netscape (December 4, 1995)
  • First standardized version (ECMAScript) in 1997
  • Second version, 1998
  • 3rd version, 1999
  • 4th version, never released
  • 5th version (ES5), December 2009
  • 6th version (ES6 or ES2015), 2015
  • 7th version (ES7 or ES2016), 2016
  • 8th version (ES8 or ES2017), 2017
  • 9th version (ES9 or ES2018), 2018
  • 10th version (ES10 or ES2019), 2019
  • 11th version (ES11 or ES2020), 2020
  • 12th version (ES12 or ES2021), 2021

JS Basics

  • Syntax
  • Printing to the console
  • Variables and Scopes
    • assignment / operator
  • basic operators (JS has a lots of them 🙃)
    • mathematical (-, +, *, /, %, ++, --, **)
    • relational (>=, <=)
    • equality (==, ===, !=, !==)
    • boolean (||, &&, !)
    • ternary ( ? : )
  • Looping constructs
    • C-style for
    • while
    • do-while
  • Control flow constructs
    • if/else
    • switch case

Variables and Scopes

Can be declared using

var
let
const

Scopes

The part of the program where a name has valid meaning or value.

  • Global Scope
  • Functional Scope
  • Block Scope
Mutable | Either be global or functional in scope
Mutable | Either global or block in scope
Immutable | Either global or block in scope

The identifier can be any text except keywords and strings starting with special chars (such as numbers)

Variables and Assignment

  • Variables in JavaScript are declared before they are used using var keyword.
  • You can declare a variable and assign a value at the same time
var foo = 6;

foo = 4;  // change variable `foo`

x += 1;
x = x + 1; // Compound Assignment Operators

Identifiers and Variable Names

Identifiers are names that play various syntactic roles in JavaScript.

  • Roughly, the first character of an identifier can be any Unicode letter, a dollar sign ($), or an underscore (_).
  • Subsequent characters can additionally be any Unicode digit. (except reserved words.)

Assignment ( = )

"set" a value to a variable (after declaration)

Compound assignment

+=

-=

*=

/=

%=

JS Basics

  • Syntax
  • Printing to the console
  • Variables and Scopes
  • basic operators
    • mathematical (-, +, *, /, %, ++, --, **)
    • relational (>=, <=)
    • equality (==, ===, !=, !==)
    • boolean (||, &&, !)
    • ternary ( ? : )
  • Looping constructs
    • C-style for
    • while
    • do-while
  • Control flow constructs
    • if/else
    • switch case

Expressions vs Statements

Statements “do things.” A program is a sequence of statements.

var x;

Expressions produce values.

3 * 6

Example

var x;
if (y >= 0) {
    x = y;
} else {
    x = -y;
}

var x = y >= 0 ? y : -y;

How to create functions?

Primarily 3️⃣ ways

  • Function Declaration
  • Function Expression
    • Anonymous Functions
  • Function Constructor

(will not be discussed today)

Function Declaraion

function NAME_OF_FUNCTION(parameters) {
  // list of statements
  // optional return
}
  • Uses the function keyword and mandatory name
  • Is not in a position of an expression
    • either at the Program level or directly in the body of another function
  • Is hoisted

Function Expressions

  • in the source code can only be defined at the expression positions
  • can have an optional name
    • When name is missing, it's an anonymous function
  • Not hoisted
var foo = function () {
  ...
};
var foo = function _foo() {
  ...
};

Optional name

Executing a function

Functions can be executed (or called) by using two parentheses, passing arguments.

function sum(a, b) {
  return a + b;
}
sum(4, 5);

a

b

One interesting thing about JS

JS won't give an error if you pass fewer or more number of arguments to a function

sum(); // ✅: a = undefined, b = undefined
sum(5); // ✅: a = 5, b = undefined
sum(5, 4) // ✅: a = 5, b = 4
sum(5, 6, 7, 8, 9)// ✅: a = 5, b = 6, 
// rest can be accessed using a special object

Should I put semicolons or not? 🤔

  • Semicolons are optional in JavaScript (for users).
  • However, it is recommended to always include them, otherwise JavaScript can guess wrong about the end of a statement.

😱

function sum(a, b) {
    return
    a + b
}
> sum(4,5)
9
function sum(a, b) {
    return
    {
      sum: a+b
    }
}

Example

Expected Output

> sum(4,5)
{ sum: 9 }
  • Semicolons terminate statements, but not blocks.
  • There is one case where you will see a semicolon after a block 🙃 :
  • a function expression is an expression that ends with a block.
  • If such an expression comes last in a statement, it is followed by a semicolon:
// Pattern: var _ = ___;
var x = 3 * 7;
var f = function () { };  // function expr. inside var decl.

How JS decides where to put a ; ?

The mechanism is called ASI (Automatic Semicolon Insertion)

Types of values in JS

  • null
  • undefined
  • numbers
  • strings
  • boolean
  • symbols
  • bigint
  • objects

JS values can be classified in two categories

  • Primitive types
  • Reference types (or objects)

JS has these types of values

no different type for ints or floats
everything (except the primitives) is object
that means arrays and functions are also objects 🤯
available for >=ES6
available for >=ES11

Primitive Values vs Objects

  • The primitive values are booleans, numbers, strings, null, undefined, symbols (ES6), and bigint.
  • All other values are objects.
> var obj1 = {};  // an empty object
> var obj2 = {};  // another empty object
> obj1 === obj2
false
> obj1 === obj1
true

Differences

  • Primitives values are compared by value and not reference
  • Primitive values are immutable

Since JS is dynamically-typed,

How can I find the type of a value? 🙋

You can use typeof operator to find the type of a value.

typeof results

undefined and null

  • Most programming languages have values denoting missing information.
  • JavaScript has two such “nonvalues,” undefined and null.
  • undefined means “no value.”
    • Uninitialized variables are undefined:
    • Missing parameters are undefined
    • If you read a nonexistent property, you get undefined
> var foo;
> foo
undefined

> function f(x) { return x }
> f()
undefined
> var obj = {}; // empty object
> obj.foo
undefined

numbers (IEEE-754 “Double”)

  • Number Literal ➡️ Just type the number

  • Only one number type (apart from bigint)

    • No integers

  • 64-bit floating point (aka double)

  • Special Numbers are

    • NaN

    • Infinity

  • Does not map well to common understanding of arithmetic:

    • 0.1 + 0.2 = 0.30000000000000004

IEEE 754

NaN (Not a Number)

It is (generally) produced by error conditions. Example:

// trying to convert to numbers
> Number('abc')
NaN
> Number(undefined)
NaN

NaN is the only value that is not equal to itself:

> NaN === NaN
false

Special numbers

⚠️ Note ⚠️

typeof NaN is 'number'  😅

> typeof NaN
"number"

Infinity and -Infinity ♾️

Bigger and (smaller) than any numeric value in JS

1 / 0 === Infinity

-1 / 0 === -Infinity

any + number * Infinity === Infinity

any + number / Infinity === 0

Number.MAX_SAFE_INTEGER

represents the maximum safe integer. ==  2 ** 53 - 1

const x = Number.MAX_SAFE_INTEGER + 1;
const y = Number.MAX_SAFE_INTEGER + 2;

console.log(x === y); // 🤦 true

Number.MIN_SAFE_INTEGER

== -Number.MAX_SAFE_INTEGER

Number.MAX_VALUE | MIN_VALUE

represents the maximum (or minimum) numeric value representable in JavaScript.

Converting (casting) to Number

Value Type Result
undefined NaN
null 0
Boolean True -> 1, false -> 0
number same number
string try to convert the string to number. Empty string is 0.
object ToPrimitive algorithm

Strings

  • No independent char type
  • Literal notation ➡️ type the text in single quote / double quote / backticks (>=ES6).
  • The backslash (\) escapes characters and produces a few control characters.
  • Single characters are accessed via square brackets notation.
'abc'
"abc"
'Did she say "Hello"?'
"Did she say \"Hello\"?"
'That\'s nice!'
"That's nice!"
'Line 1\nLine 2'  // newline
'Backlash: \\'
> var str = 'abc';
> str[1]
'b'

Some common operations

Concatenation ( + )

> var messageCount = 3;
> 'You have ' + messageCount + ' messages'
'You have 3 messages'
var str = '';
str += 'Multiple ';
str += 'pieces ';
str += 'are concatenated.';
console.log(str)
'Multiple pieces are concatenated.'

Find length (number of characters)

let name = ''
> name.length
0
let name = 'arfat'
> name.length
5

Comparison (“dictionary” or “lexicographical” order)

'a' === 'a' // true
'a' === 'b' // false
'a' > 'b' // false 
'A' > 'a' // false
'1' > 'a' // false
'Bee' > 'Be' // true: longer strings are greater if all else is equal

Booleans

There are two boolean values in JS.

true
false

Truthy values: Non-boolean values which evaluate to true

Falsy values: Non-boolean values which evaluate to false

These values are falsy (or false) in JS

  • 0
  • -0
  • null
  • undefined
  • false
  • NaN
  • ''
  • 0n
Number Zero
Negative zero -- 🤔 (an artifact of IEEE 754) 
Empty String
The n denotes bigint number. 0n is bigint 0.
  • Array (as Objects)

  • Difference between Java arrays

    • Arrays are maps in JS

    • JS Arrays can contain any element type simultaneously

    • No need to specify the size upfront. Can extend dynamically.

  • Array Methods

    • map

    • filter

    • forEach

    • ...

  • mutating and non-mutating methods

Arrays

  • An array is a map from indices (natural numbers, starting at zero) to arbitrary values.

  • The values are called the array’s elements.

  • The most convenient way of creating an array is via an array literal. ✅

> var arr = [ 'a', 'b', 'c' ]; // array literal
> arr[0]  // get element 0
'a'
> arr[0] = 'x';  // set element 0 to 'x'
> arr
[ 'x', 'b', 'c' ]
  • The ECMAScript standard specifies arrays as maps (dictionaries) from indices to values.

Arrays Can Also Have Properties

  • Those are not considered part of the actual array; that is, they are not considered array elements.

> var arr = [ 'a', 'b' ];
> arr.foo = 123;
> arr
[ 'a', 'b' ]
> arr.foo
123

Since arrays are just objects

The .length property returns the number of elements currently present in the array.

Other ways of creating an array

Array Constructor ☠️

> var arr = new Array(2);
> arr.length
2
> arr  // two holes plus trailing comma (ignored!)
[ , ,]

// The same as ['a', 'b', 'c']:
var arr1 = new Array('a', 'b', 'c'); 
// ☠️ AVOID this.

An empty array with a given length has only holes in it!

> new Array(2)  // alas, not [ 2 ]
[ , ,]

> new Array(5.7)  // alas, not [ 5.7 ]
RangeError: Invalid array length

> new Array('abc')  // ok
[ 'abc' ]

Array.of()

Creates a new Array instance from a variable number of arguments, regardless of number or type of the arguments.

Array.of(7); // [7]
Array(7); // array of 7 empty slots

Array.of(1, 2, 3); // [1, 2, 3]
Array(1, 2, 3);    // [1, 2, 3]

How to check if a value is array⁉️

You can't use typeof, since the output will be 'object'

instanceof ☠️☠️

if (arr instanceof Array) {
  console.log('arr is an array')
}

Array.isArray

if (Array.isArray(arr)) {
  console.log('arr is an array')
}

In some rare cases, instanceof can give wrong answers.

Array Methods

  • Destructive methods
  • Non-destructive methods
    • Iteration methods
      • for-of loops
      • forEach
    • Searching Methods
    • Concatenation
    • Transformation

Broadly two kinds of methods

💡 Pro tip 💡: It's a good programming practice to minimize the use of destructive methods.

Array#push

Red means destructive

let livestock = ["🐷", "🐮", "🐔"];
livestock.push("🐴", "🐮");
// ["🐷", "🐮", "🐔", "🐴", "🐮"]

Array#pop

let livestock = ["🐷", "🐮", "🐔"];
let lastElem = livestock.pop();
console.log(lastElem) // "🐔"
console.log(livestock) // ["🐷", "🐮"]

Array#shift

const array1 = [1, 2, 3];
const firstElement = 
      array1.shift();
console.log(array1); // [2, 3]
console.log(firstElement); // 1

Array#unshift

let train = ["🚃", "🚃"];
train.unshift("🚂");
// ["🚂", "🚃", "🚃"]

Array#forEach

const numbers = [1, 2, 3, 4, 5, 6];

numbers.forEach(function (el) {
  console.log(el);
});
  • Takes a callback as an argument
  • The callback receives the elements as arguments
  • The return value of callback is not used
  • break and continue don't work

for of loops (Not really an Array method)

const numbers = [1, 2, 3, 4];
for (const number of numbers) {
  console.log(number);
}

Finding elements

Array#indexOf  ☠️

let array = ['a', 1, '2', NaN];

console.log(array.indexOf('a')); // 0
console.log(array.indexOf(NaN)); // -1

returns index of the element or -1

let array = ['a', 1, '2', NaN];

console.log(array.includes('a')); // true
console.log(array.includes(NaN)); // true
console.log(array.includes('b')); // false
console.log(array.includes('a', 2)); // false

Array#includes

Array#lastIndexOf  ⚠️

const animals = [
  'Dodo', 
  'Tiger', 
  'Penguin', 
  'Dodo',
  NaN
];

animals.lastIndexOf('Dodo') // 3

animals.lastIndexOf('Tiger') // 1

animals.lastIndexOf(NaN) // -1

Array#reverse

let arr = [ 'a', 'b', 'c' ];
arr.reverse()
// [ 'c', 'b', 'a' ]
arr // reversing happened in-place
// [ 'c', 'b', 'a' ]

Array#fill

[1, 2, 3].fill(4); // [4, 4, 4]
[1, 2, 3].fill(4, 1); // [1, 4, 4]
[1, 2, 3].fill(4, 1, 2); // [1, 4, 3]
[1, 2, 3].fill(4, 1, 1); // [1, 2, 3]
[1, 2, 3].fill(4, 3, 3); // [1, 2, 3]

changes all elements in an array to a static value, from a start index (default 0) to an end index (default array.length).

Array#sort ⚠️⚠️

> let arr = ['banana', 'apple', 'pear', 'orange'];
> arr.sort()
[ 'apple', 'banana', 'orange', 'pear' ]
> arr  // sorting happened in place
[ 'apple', 'banana', 'orange', 'pear' ]
let array = [1, 10, 101, 2, 3, 1001];

array.sort();

console.log(array);
// [1, 10, 1001, 101, 2, 3];
  • Array#concat
    • merge two or more arrays
  • Array#join
    • join the elements into a string using a separator
  • Array#slice
    • returns a shallow copy of a portion of an array
> [3, 4, 5].join('-')
'3-4-5'
> [3, 4, 5].join()
'3,4,5'
> [3, 4, 5].join('')
'345'

> [undefined, null].join('#')
'#'
> [ 'a', 'b', 'c', 'd' ].slice(1, 3)
[ 'b', 'c' ]

Array#map

  • takes a callback as an argument
  • transforms each element of the array using the callback
  • returns a new array with the transformed elements
  • originalArray.length === newArray.length
const hungryMonkeys = ['🐒', '🦍', '🦧'];
const fedMonkeys = hungryMonkeys.map(function (monkey) {
  return monkey + '🍌';
});
// ["🐒🍌", "🦍🍌", "🦧🍌"]
const numbers = [1, 2, 3, 4, 5, 6];

const squares = numbers.map(function (el) {
  return el * el;
});

console.log(squares);
// [ 1, 4, 9, 16, 25, 36 ]

Array#filter

  • takes a callback as an argument
  • executes the callback on each element
  • if callback returns true, the value is included in the new returned array
  • 0 <= newArray.length <= originalArray.length
    
const numbers = [1, 2, 3, 4, 5, 6];

const evens = numbers.filter(function (el) {
  return el % 2 === 0;
});

console.log(evens);
// [ 2, 4, 6 ]

Error Handling

Exceptions are anomalous or exceptional conditions that require special processing during the execution of a program.

throw statement

The throw statement throws a user-defined exception.

Important Note

  • Execution of the current function will stop (the statements after throw won't be executed), and control will be passed to the first catch block in the call stack.
  • If no catch block exists among caller functions, the program will terminate.
throw expression;
function a() {
  b();
}

function b() {
  c();
}

function c() {
  d();
}

function d() {
  throw 'error in d';
}

a();
  • The runtime system searches the call stack for a method that contains a block of code that can handle the exception.
  • This block of code is called an exception handler.
  • What if no exception?
try {
  try_statements
}
catch (exception_var) {
  catch_statements
}
finally {
  finally_statements
}

Catching an exception

function a() {
  b();
}

function b() {
  try {
    c();
    console.log('after c()')
  } catch (ex) {
    console.log('caught this exception -- ', ex);
  }
}

function c() {
  d();
}

function d() {
  throw 'error in d';
}

a();

Error

It's not a good idea to throw random expressions. You should always throw an object of the Error class (or something similar).

function a() {
  b();
}

function b() {
  try {
    c();
  } catch (ex) {
    console.log('caught this exception -- ');
    console.log(ex);
  }
}

function c() {
  d();
}

function d() {
  throw new Error('error in d');
}

a();

The finally Block

The finally block always executes when the try block exits.

It always executes, regardless of whether an exception was thrown or caught.

openMyFile();
try {
  // tie up a resource
  writeMyFile(theData);
} finally {
  closeMyFile(); // always close the resource
}

JavaScript’s Type System

  • Static Versus Dynamic

  • Static Typing Versus Dynamic Typing

  • Static Type Checking Versus Dynamic Type Checking

  • JS Types

  • Coercion

  • == vs ===

Static vs Dynamic

In the context of language semantics and type systems, “static” usually means “at compile time” or “without running a program”, while “dynamic” means “at runtime”.

Static typing versus dynamic typing

  • In a statically typed language, variables, parameters and members of objects (JavaScript calls them properties) have types that the compiler knows at compile time.
  • The compiler can use that information to perform type checks and to optimize the compiled code.

Static type checking versus dynamic type checking

  • If you have type information, you can check whether a value that is transported to another location (via a function call, an assignment, etc.) has the correct type.
  • Statically type-checked languages perform this kind of check at compile time, dynamically type-checked languages at runtime.
  • A language can be both statically type-checked and dynamically type-checked.

In JavaScript, the main way of dealing with a value whose type doesn’t fit is to coerce it to the correct type. Coercion means implicit type conversion. Most operands coerce:

 > '3' * '4'
    12
  • Implicit coercion
  • Explicit coercion

JS types

JS has 6 (5 primitive + 1 object in ES5) types that are dynamically typed and (mostly) dynamically typed-checked.

Coercion

== vs ===

Strict equality (===) and strict inequality (!==) consider only values that have the same type to be equal.

 Normal (or “lenient”) equality (==) and inequality (!=) try to convert values of different types before comparing them as with strict (in)equality.

> undefined == null
true
> 1 == true
true
> 0 == false
true
> '' == false  
true
> '1' == true
true

Coercion

true + false
1
12 / "6"
2
"number" + 15 + 3
"number153"
15 + 3 + "number"
"18number"
[1] > null
true
"foo" + + "bar"
"fooNaN"
'true' == true
false
false == 'false'
false
null == ''
false
!!"false" == !!"true"
true
"Why am I a " + typeof + "";
"Why am I a number"

Functions can act in various ways in JavaScript. Let’s look at them —

Traditional Functions (that is, outside any object)

function add1(num1, num2) { // function declaration
 return num1 + num2;
}
const add2 = function(num1, num2) { // function expression
 return num1 + num2;
}

Object’s methods (inside an object)

  • In this case, the functions are embedded in objects. In most cases, they are supposed to act on data stored in the object itself.
  • For example, in the code below, getName() method returns the name property stored in details object.
const details = {
  name: 'Arfat',
  getName: function () {
  return this.name;
  }
}
details.getName(); // 'Arfat'

Constructor Functions

  • Constructor functions “construct” objects. They are equivalent to classes in other languages.
  • A class is considered as a factory for the production of “instances” or “objects”.
  • Since JavaScript has no concept of a class (even though it has class keyword), functions rise up to the task.
  • A function, when used with the new operator, is called a constructor function. The new operator changes the behavior of the function.
function Person(name) {
  this.name = name;
}
const person1 = new Person('Arfat');
console.log(person1); 
// Person { name: 'Arfat' }

Factory (object-oriented programming)

In object-oriented programming (OOP), a factory is an object for creating other objects – formally a factory is a function or method that returns objects of a varying prototype or class from some method call, which is assumed to be "new".

  • A factory is an abstraction of a constructor of a class, while in prototype-based programming a factory is an abstraction of a prototype object.
  • A constructor is concrete in that it creates objects as instances of a single class, and by a specified process (class instantiation), while a factory can create objects by instantiating various classes, or by using other allocation schemes such as an object pool.
var e = 10;
function sum(a) {
  return function(b) {
    return function(c) {
      return function(d) {
        return a + b + c + d + e;
      }
    }
  }
}

sum(1)(2)(3)
function a() {
  let fn;
  {
    var x = 5;
    fn = function() {
      console.log(x);
    }
  }

  return fn;
}

var x = 10;
const b = a();
b();
var a = 100;

function outer(x) {
  var a = 10;
  return function (y) {
    return a + y;
  }
}

a = 50;

var inner = outer(20);

function abc() {
  var a = 30;
  console.log(inner(5));
}

abc();

Executable Code and Execution Contexts

  • A Lexical Environment is a specification type used to define the association of Identifiers to specific variables and functions based upon the lexical nesting structure of ECMAScript code.
  • A Lexical Environment consists of an Environment Record and a possibly null reference to an outer Lexical Environment.
  • Usually a Lexical Environment is associated with some specific syntactic structure of ECMAScript code such as a FunctionDeclaration, a BlockStatement, or a Catch clause of a TryStatement and a new Lexical Environment is created each time such code is evaluated.

An Environment Record records the identifier bindings that are created within the scope of its associated Lexical Environment. It is referred to as the Lexical Environment's EnvironmentRecord.

  • The outer environment reference is used to model the logical nesting of Lexical Environment values.
  • The outer reference of a (inner) Lexical Environment is a reference to the Lexical Environment that logically surrounds the inner Lexical Environment.
  • An outer Lexical Environment may, of course, have its own outer Lexical Environment.
  • A Lexical Environment may serve as the outer environment for multiple inner Lexical Environments.

For example, if a FunctionDeclaration contains two nested FunctionDeclarations then the Lexical Environments of each of the nested functions will have as their outer Lexical Environment the Lexical Environment of the current evaluation of the surrounding function.

  • A global environment is a Lexical Environment which does not have an outer environment.
  • The global environment's outer environment reference is null.
  • A global environment's EnvironmentRecord may be prepopulated with identifier bindings and includes an associated global object whose properties provide some of the global environment's identifier bindings.

As ECMAScript code is executed, additional properties may be added to the global object and the initial properties may be modified.

  • A function environment is a Lexical Environment that corresponds to the invocation of an ECMAScript function object.
  • A function environment may establish a new this binding.
  • A function environment also captures the state necessary to support super method invocations.

Environment Records

  • A function Environment Record is a declarative Environment Record that is used to represent the top-level scope of a function and, if the function is not an ArrowFunction, provides a this binding.
  • If a function is not an ArrowFunction function and references super, its function Environment Record also contains the state that is used to perform  super method invocations from within the function.
  • Each declarative Environment Record is associated with an ECMAScript program scope containing variable, constant, let, class, module, import, and/or function declarations. A declarative Environment Record binds the set of identifiers defined by the declarations contained within its scope.

Execution Contexts

  • An execution context is a specification device that is used to track the runtime evaluation of code by an ECMAScript implementation.
  • At any point in time, there is at most one execution context per agent that is actually executing code.
  • This is known as the agent's running execution context.
  • The execution context stack is used to track execution contexts. The running execution context is always the top element of this stack.

Execution contexts for ECMAScript code have the additional state components listed in Table.

Component Purpose
LexicalEnvironment Identifies the Lexical Environment used to resolve identifier references made by code within this execution context.
VariableEnvironment Identifies the Lexical Environment whose EnvironmentRecord holds bindings created by VariableStatements within this execution context.

First-class functions

A first-class function is one that may participate as a normal data, i.e. be created literally at runtime, be passed as an argument, or be returned as a value from another function.

Free variable

A free variable is a variable which is used by a function, but is neither a parameter, nor a local variable of the function.

Closure

A closure is a pair consisting of the function code and the environment in which the function is created.

Segment 2

function f() {
  this.name = 'arfat';
}

f();
function f() {
  'use strict'
  this.name = 'arfat';
}

f();
const obj = {
  name: 'Arfat',
  f: function() {
    console.log(this.name);
  }
};

obj.f();
const obj = {
  name: 'Arfat',
  f: function() {
    console.log(this.name);
  }
};

var g = obj.f;
g();
setTimeout(obj.f, 2000);
var obj = {
  name: 'Jane',
  friends: [ 'Tarzan', 'Cheeta' ],
  loop: function () {
      this.friends.forEach(
           function(friend) {  // (1)
              console.log(this.name+' knows '+friend);  // (2)
          }
      );
  }
};

obj.loop();

Objects

An object is a

collection of properties

A property is a
named container for a value
w/ some additional attributes

Definition

The name of a property  is called a key ;
thus, an object  can be considered as
a collection of key-value pairs .

There are similar concepts in other programming languages,
e.g., Map, Dictionary, Associative Array, Symbol Table, Hash Table , ...

  • Property Accessors (Dot and square notations)

  • this in objects

  • Other gotchas when using this.

    • Functions Inside Methods Shadow this

    • Losing this When Extracting a Method

  • Inheritance

    • Javascript inheritance by examples

    • Setting and Deleting Affects Only Own Properties

    • Sharing Data Between Objects via a Prototype

    • Prototypal Chain

Review

Properties

  • all objects in JavaScript are maps (dictionaries) from strings to values.

  • A (key, value) entry in an object is called a property .  The key of a property is always a text string.

  • 3 Kinds of Properties

  • Properties (or named data properties)

  • Accessors (or named accessor properties)

  • Internal properties

    • Exist only in the ECMAScript language specification.

 

Accessing Properties

Dot Notation

var jane = {
  name: 'Jane',

 'desc.func': function () {
      return 'Person named ' + this.name;
  },
};
$ jane.name

// 'jane'
$ jane['desc.func']

// [Function]

Bracket Notation

this in objects

this  refers to the object on which the method has been invoked

> var obj = { method: returnThisStrict };
> obj.method() === obj
true

Normal functions in sloppy mode

function returnThisSloppy() {
    return this
}
> returnThisSloppy() === window
true

Normal functions in strict mode

function returnThisStrict() {
    'use strict';
    return this
}

> returnThisStrict() === undefined
true

Pitfalls

Losing this When Extracting a Method

var counter = {
    count: 0,
    inc: function () {
        this.count++;
    }
}
  • We have called the value of counter.inc  as a function.

  • Hence, this  is the global object and we have performed window.count++ .

  • window.count  does not exist and is undefined . Applying the ++  operator to it sets it to NaN.

  • Use strict mode for avoiding this.

> var func = counter.inc;
> func()
> counter.count  // didn’t work
0

How to properly extract a method

> var func3 = counter.inc.bind(counter);
> func3()
> counter.count  // it worked!
1

Callbacks and extracted methods

function callIt(callback) {
    callback();
}
> callIt(counter.inc)

> callIt(counter.inc.bind(counter))

Pitfall

Functions Inside Methods Shadow this

var obj = {
    name: 'Jane',
    friends: [ 'Tarzan', 'Cheeta' ],
    loop: function () {
        'use strict';
        this.friends.forEach(
            function (friend) {  // (1)
                console.log(this.name+' knows '+friend);  // (2)
            }
        );
    }
};

> obj.loop()

What to do?

Workaround 1: that = this

loop: function () {
    'use strict';
    var that = this;
    this.friends.forEach(function (friend) {
        console.log(that.name+' knows '+friend);
    });
}

Workaround 2: bind()

loop: function () {
    'use strict';
    this.friends.forEach(function (friend) {
        console.log(this.name+' knows '+friend);
    }.bind(this));  // (1)
}

Workaround 3: a thisValue for forEach()

this.friends.forEach(function (friend) {
        console.log(this.name+' knows '+friend);
}, this);

How this changes?

Global Context

In the global execution context (outside of any function), this refers to the global object whether in strict mode or not.

Function context

Inside a function, the value of this depends on how the function is called.

Simple Call

Since the following code is not in strict mode, and because the value of this is not set by the call, this will default to the global object, which is window in a browser.

function f1() {
  return this;
}

// In a browser:
f1() === window; // true 

// In Node:
f1() === global; // true

Arrow functions

In arrow functions, this retains the value of the enclosing lexical context's this. In global code, it will be set to the global object:

As an object method

When a function is called as a method of an object, it's this is set to the object the method is called on.

this on the object's prototype chain

var o = {f: function() { return this.a + this.b; }};
var p = Object.create(o);
p.a = 1;
p.b = 4;

console.log(p.f()); // 5

 If the method is on an object's prototype chain, this refers to the object the method was called on, as if the method were on the object.

As a constructor

When a function is used as a constructor (with the new keyword), its this is bound to the new object being constructed.

As a DOM event handler

When a function is used as an event handler, its this is set to the element the event fired from (some browsers do not follow this convention for listeners added dynamically with methods other than addEventListener()).

In an inline event handler

When the code is called from an inline on-event handler, its this is set to the DOM element on which the listener is placed:

<button onclick="alert((function() { return this; })());">
  Show inner this
</button>

Introduction to JavaScript

By Arfat Salman

Introduction to JavaScript

A Brief intro of JS.

  • 1,881