Advanced Web Programming
Part 04 – Advanced JavaScript
Dr. Amjad AbuHassan
11/30/2024 Dr. Amjad AbuHassan 1
Introduction to ES6+
● ES6 (ECMAScript 2015): Major update to JavaScript
● New Features: Arrow functions, classes, modules, template literals, destructuring,
and more
● Importance: Modernizes JavaScript, improves readability and maintainability
11/30/2024 Dr. Amjad AbuHassan 2
Hoisting
● Hoisting in JavaScript refers to the behavior where the declarations of functions,
variables, or classes are moved to the top of their containing scope.
● Hoisting is a feature you might encounter in some programming languages like
JavaScript but not in others. It's a unique aspect of how the JavaScript interpreter
processes code.
● Function Hoisting
● Variable Hoisting
● Class Hoisting
11/30/2024 Dr. Amjad AbuHassan 3
Outline
● Variables
● Arrow Functions vs Function Expression
● Modules
● Promises and Asynchronous Programming
● Closures
● Generators
● Higher-Order Functions
● this Keyword
11/30/2024 Dr. Amjad AbuHassan 4
Variables
11/30/2024 Dr. Amjad AbuHassan 5
Variables Recap
● We can declare variables using
● var
● let
● const
● While all these variable declarations are hoisted, they each behave differently
11/30/2024 Dr. Amjad AbuHassan 6
var Recap
● Prior to ES6, var was the primary way to declare variables.
● Issues with var led to the introduction of let and const in ES6.
● Variables declared with var outside any function are globally scoped.
● Variables declared within a function are scoped to that function.
11/30/2024 Dr. Amjad AbuHassan 7
Hoisting var Variables Case 1
● Hoisting Behavior:
● Declarations using var are hoisted to the top of their scope.
● var variables are initialized with undefined
● Understanding Errors:
● Accessing undeclared variables throws a ReferenceError.
11/30/2024 Dr. Amjad AbuHassan 8
Hoisting var Variables Case 2
● Hoisting Behavior:
● Hoisting moves variable declarations to the top of
their own scope (global or local).
● Declarations are hoisted, but initializations stay in
place.
● Scope Matters:
● Accessing a variable outside its declared scope
results in a ReferenceError.
● Inside the scope, you can access the variable before
its declaration due to hoisting.
11/30/2024 Dr. Amjad AbuHassan 9
Problems Associated with var
● var is not block-scoped (does not respect {} blocks like if, for).
● Variables can be unintentionally redefined within blocks.
● Re-declaring variables can overwrite existing variables, leading to bugs.
11/30/2024 Dr. Amjad AbuHassan 10
Need For let and const
● To address these issues, ES6 introduced let and const.
● Block Scope: Variables declared with let and const are block-scoped.
● Prevent Re-declaration: let and const do not allow re-declaration in the same
scope.
● Result: Enhanced code reliability and reduced bugs.
11/30/2024 Dr. Amjad AbuHassan 11
let Recap
● let is now the recommended way to declare variables.
● Variables declared with let are block-scoped.
11/30/2024 Dr. Amjad AbuHassan 12
Updating and Re-declaring let Variables
● We can update a let variable within its scope.
● We cannot re-declare a let variable within the same scope (SyntaxError)
● We can declare the same variable name in different scopes without errors.
11/30/2024 Dr. Amjad AbuHassan 13
Hoisting let Variables
● Attempting to access a let variable before initialization leads to a ReferenceError
because it's hoisted but uninitialized.
● This behavior is due to the Temporal Dead Zone, a phase where the variable exists
but cannot be accessed.
● Variables declared with var do not have this issue since they are initialized with
undefined upon hoisting.
11/30/2024 Dr. Amjad AbuHassan 14
const Recap
● Variables declared with const hold
constant values within their scope.
● const declarations are block scoped,
similar to let.
● We cannot re-declare a const
variable within the same scope.
● Every const variable must be
initialized when it's declared.
11/30/2024 Dr. Amjad AbuHassan 15
cont Behavior with Objects
● We cannot reassign a const object, but we can modify its properties.
11/30/2024 Dr. Amjad AbuHassan 16
Hoisting const Variables
● Hoisted but Uninitialized: const variables are hoisted to the top of their scope but
are uninitialized, making them inaccessible until their line.
● Temporal Dead Zone: The TDZ prevents access to const variables before
initialization.
● Reference Errors: Attempting to access a const variable before initialization results
in a ReferenceError.
11/30/2024 Dr. Amjad AbuHassan 17
Differences Summary var, let, and const
● Scope:
● var declarations are function scoped or globally scoped.
● let and const are block scoped.
● Updating Variables:
● var variables can be updated and re-declared within their scope.
● let variables can be updated but not re-declared within the same scope.
● const variables can neither be updated nor re-declared.
11/30/2024 Dr. Amjad AbuHassan 18
Differences Summary var, let, and const
● Hoisting Behavior:
● All are hoisted to the top of their scope.
● var variables are initialized with undefined.
● let and const variables are not initialized (Temporal Dead Zone).
● Initialization Requirement:
● var and let can be declared without initialization.
● const must be initialized during declaration.
11/30/2024 Dr. Amjad AbuHassan 19
Arrow Functions vs. Function
Expressions
11/30/2024 Dr. Amjad AbuHassan 20
Introduction
● Functions are essential in JavaScript for encapsulating logic, promoting reusability,
and building modular applications.
● Two primary ways to define functions:
● Arrow Functions
● Function Expressions (Regular Functions)
● Understanding their syntax, behavior, and use cases helps in writing efficient and
maintainable code.
11/30/2024 Dr. Amjad AbuHassan 21
Function Expressions (Regular Functions)
● Definition: Functions defined using the function keyword and assigned to a
variable.
● The function can be used before its declaration due to hoisting.
11/30/2024 Dr. Amjad AbuHassan 22
Handling this Keyword
● this is dynamic and determined by how the function is called.
● Useful for accessing object properties within methods.
11/30/2024 Dr. Amjad AbuHassan 23
Use Cases
● Object Methods: Defining methods that need access to the object's properties via
this.
● Constructor Functions: Creating templates for objects with shared methods.
● Callbacks: Passing functions as arguments where this context may vary.
11/30/2024 Dr. Amjad AbuHassan 24
Function Hoisting Case 1
● Hoisting allows functions to be called before they are defined in the code, ensuring
smooth execution without errors.
● This makes the function (and its logic) accessible even before its declaration line.
11/30/2024 Dr. Amjad AbuHassan 25
Function Hoisting Case 2
11/30/2024 Dr. Amjad AbuHassan 26
Arrow Functions
● Syntax: Concise syntax for writing functions
● Benefits:
● Shorter function expressions
● Lexical this binding
11/30/2024 Dr. Amjad AbuHassan 27
Handling this Keyword
● Lexical this Binding: Inherits this from the enclosing scope.
● Does not have its own this context.
11/30/2024 Dr. Amjad AbuHassan 28
Limitations of Arrow Functions
● Cannot be used as constructors: No new keyword
● No arguments object: Use rest parameters instead
● No this or super binding: Always lexical
11/30/2024 Dr. Amjad AbuHassan 29
Use Cases
● Array Methods: Ideal for concise callbacks in methods like map, filter, and reduce
● Consistent this Context: When the this value should remain the same.
● Short Inline Functions: Perfect for simple, one-liner functions.
11/30/2024 Dr. Amjad AbuHassan 30
Advanced Use of Arrow Functions
● Higher-Order Functions: Pass arrow functions as arguments
● Callbacks:
11/30/2024 Dr. Amjad AbuHassan 31
Arrow Functions vs. Function Expressions
● this Binding:
● Arrow Functions: Use lexical scoping; this is inherited from the parent scope.
● Function Expressions: this is dynamic and depends on the caller.
● Arguments Object:
● Arrow Functions: Do not have their
own arguments object.
● Use rest parameters (...args) if needed.
● Function Expressions: Have access to the arguments object.
11/30/2024 Dr. Amjad AbuHassan 32
Arrow Functions vs. Function Expressions cont
Function Hoisting
● Arrow Functions:
● Not hoisted; cannot be used before they are defined.
● Function Expressions:
● If declared with var, they are hoisted but initialized as undefined.
● If declared with let or const, they are not hoisted.
11/30/2024 Dr. Amjad AbuHassan 33
Anonymous Function
● Definition: An anonymous function is a function without a name.
● Useful for one-time operations or when the function name is unnecessary.
● Cannot call themselves recursively unless assigned to a variable.
● Anonymous functions may appear as <anonymous> in stack traces, making
debugging more challenging.
11/30/2024 Dr. Amjad AbuHassan 34
Use Cases Functions
● Callbacks: Functions passed as arguments to other functions.
● Event Handlers:
● The function passed to addEventListener is anonymous.
● Immediately Invoked Function Expressions (IIFEs): Functions that are executed
immediately after being defined.
11/30/2024 Dr. Amjad AbuHassan 35
Use Cases cont.
● Functional Programming
● Arrow functions are inherently anonymous.
11/30/2024 Dr. Amjad AbuHassan 36
Conclusion
● No One-Size-Fits-All: Both arrow functions and function expressions have their
advantages.
● Choose Based on Needs:
● Use arrow functions for concise syntax and when lexical this is desired.
● Use function expressions when dynamic this or access to arguments is required.
● Prioritize Maintainability: Write clear, consistent, and maintainable code.
● Let the Code Guide You: Your specific coding scenario should dictate the function
type choice.
11/30/2024 Dr. Amjad AbuHassan 37
Modules
11/30/2024 Dr. Amjad AbuHassan 38
Modules
● Modules are a way to organize and encapsulate code into separate files or units.
● Encapsulation: preventing variables and functions from polluting the global
namespace
● Reusability: reuse code across different parts of an apps or even projects
● Maintainability: Breaking code into modules makes it easier to maintain and
understand, especially in large codebases.
● Dependency Management: Modules allow for explicit declaration of
dependencies, making it clear which parts of code rely on others.
11/30/2024 Dr. Amjad AbuHassan 39
Module Systems in JavaScript
● CommonJS Modules
● ES6 Modules (ESM)
● AMD (Asynchronous Module Definition)
● UMD (Universal Module Definition)
● Revealing Module Pattern
11/30/2024 Dr. Amjad AbuHassan 40
CommonJS Modules
● Used primarily in Node.js.
● Modules are loaded synchronously.
11/30/2024 Dr. Amjad AbuHassan 41
ES6 Modules (ESM)
● Introduced in ECMAScript 2015 (ES6).
● Native module system for JavaScript.
● Supports both synchronous and
asynchronous loading.
● Supported in modern browsers and
Node.js (with some configurations).
11/30/2024 Dr. Amjad AbuHassan 42
Exporting from a Module
● Named Exports:
● Allows you to export multiple values.
● Must be imported using the same names.
● Default Exports:
● Allows you to export a single default value.
● Can be imported with any name.
11/30/2024 Dr. Amjad AbuHassan 43
Importing Modules
11/30/2024 Dr. Amjad AbuHassan 44
Modules in Browsers
● Script Type Module:
● To use ES6 modules in browsers, include type="module" in the script tag.html
<script type="module" src="main.js"></script>
● Modules are loaded asynchronously.
● Module scripts are deferred by default, executing after the document has been parsed.
11/30/2024 Dr. Amjad AbuHassan 45
Modules in Node.js
● Historically, Node.js has used CommonJS modules (require and module.exports).
● ES Modules (import and export) are now supported in Node.js.
● To use ES modules, you can:
● Set "type": "module" in package.json.
● Use .mjs extension for your modules.
11/30/2024 Dr. Amjad AbuHassan 46
Dynamic Imports
● Definition: Allow modules to be loaded asynchronously
● Use Cases: Code splitting, lazy loading
11/30/2024 Dr. Amjad AbuHassan 47
Promises and Asynchronous
Programming
11/30/2024 Dr. Amjad AbuHassan 51
Introduction to Asynchronous Programming
● Definition: Allows code to run independently of other tasks.
● Importance: Improves performance and responsiveness.
● Common Use Cases: Network requests, file operations, timers, user interactions.
11/30/2024 Dr. Amjad AbuHassan 52
Callback Functions
● Definition: Functions passed as
arguments to other functions.
● Usage: Executed after a certain
task is completed.
11/30/2024 Dr. Amjad AbuHassan 53
The Callback Hell Problem
● Definition: The issue of
deeply nested callbacks.
● Causes: Asynchronous tasks
depending on each other.
● Challenges: Difficult to
read, maintain, and debug.
11/30/2024 Dr. Amjad AbuHassan 54
Introduction to Promises
● Definition: Objects representing
the eventual completion or failure
of an asynchronous operation.
● States: Pending, Fulfilled,
Rejected.
● Benefits: Simplifies asynchronous
code, improves readability, and
reduces nesting.
11/30/2024 Dr. Amjad AbuHassan 55
Using Promises
● then Method: Handles fulfilled
promises.
● catch Method: Handles rejected
promises.
● Chaining: Allows for sequential
execution of asynchronous operations.
11/30/2024 Dr. Amjad AbuHassan 56
Chaining Promises
● Definition: Sequentially
executing multiple
asynchronous operations.
● Benefits: Improved
readability and
maintainability.
11/30/2024 Dr. Amjad AbuHassan 57
Promisifying Callback Functions
● Definition: Converting callback-based
functions to return promises.
● Benefits: Simplifies the use of
existing callback-based APIs.
11/30/2024 Dr. Amjad AbuHassan 58
Async/Await
● Definition: Syntactic sugar over
promises for writing
asynchronous code.
● Benefits: More readable and
maintainable asynchronous code,
easier error handling.
11/30/2024 Dr. Amjad AbuHassan 59
Handling Multiple Promises
● Promise.all: Waits for all
promises to resolve or any to reject.
● Promise.race: Resolves or
rejects as soon as one promise
resolves or rejects.
● Use Cases: Coordinating multiple
asynchronous operations, handling
the fastest operation.
11/30/2024 Dr. Amjad AbuHassan 60
Promise.any
● Resolves with the first fulfilled promise
11/30/2024 Dr. Amjad AbuHassan 61
Promise. allSettled
● Waits for all promises to settle, regardless of outcome.
11/30/2024 Dr. Amjad AbuHassan 62
Error Handling in Promises
● Chained catch: Catches
errors in the promise
chain.
● Multiple catch Blocks:
● Best Practices: Use
try/catch with
async/await, handle
errors at each step.
11/30/2024 Dr. Amjad AbuHassan 63
Best Practices for Promises and Async/Await
● Avoid nested promises: Use chaining
instead.
● Handle errors properly: Use catch
with promises and try/catch with
async/await.
● Keep functions pure: Avoid side
effects in promise chains.
● Use finally for cleanup:
11/30/2024 Dr. Amjad AbuHassan 64
OR
11/30/2024 Dr. Amjad AbuHassan 65
Closures
11/30/2024 Dr. Amjad AbuHassan 69
Introduction to Closures
● Definition: A closure is a function
that has access to its own scope,
the scope of the outer function,
and the global scope.
● Scope Chain: Closures can access
variables from their own scope
and any outer functions' scopes.
11/30/2024 Dr. Amjad AbuHassan 70
Practical Uses of Closures
● Data Privacy: Encapsulating data and
creating private variables.
● Callback Functions: Preserving data in
asynchronous operations.
11/30/2024 Dr. Amjad AbuHassan 71
Closures for State Management
● Definition: Using
closures to manage
state in JavaScript.
11/30/2024 Dr. Amjad AbuHassan 72
Common Patterns Using Closures
● Module Pattern: Encapsulates private
data and exposes public methods.
11/30/2024 Dr. Amjad AbuHassan 73
Common Patterns Using Closures cont.
● Function Factories: Functions that
return other functions.
11/30/2024 Dr. Amjad AbuHassan 74
Generators in JavaScript
11/30/2024 Dr. Amjad AbuHassan 75
Introduction to Generators
● Definition: Generators are special functions that can pause and resume their
execution.
● Syntax: Defined using the function* keyword.
● Use Cases: Useful for asynchronous operations, lazy evaluation, and implementing
iterators.
11/30/2024 Dr. Amjad AbuHassan 76
Basic Syntax of Generators
● Generator Function Syntax:
● Calling a Generator:
11/30/2024 Dr. Amjad AbuHassan 77
yield Keyword
● Pausing Execution: yield pauses
the generator's execution and
returns a value.
● Resuming Execution: The
generator resumes from where it
left off after yield when next()
is called.
11/30/2024 Dr. Amjad AbuHassan 78
Iterating Over Generators
● Generators as Iterators: Generators are
naturally iterable.
● Using for...of Loop:
● Example with next():
11/30/2024 Dr. Amjad AbuHassan 79
Generator Delegation with yield*
● Delegating Generators: A generator
can delegate part of its operation to
another generator.
11/30/2024 Dr. Amjad AbuHassan 80
Generators and Asynchronous Programming
● Asynchronous Flow Control:
Generators can be combined with
Promises to manage
asynchronous code.
● Concept: Generators allow
pausing and resuming of
asynchronous operations.
11/30/2024 Dr. Amjad AbuHassan 81
Advanced Generator Techniques
● Passing Arguments to next():
11/30/2024 Dr. Amjad AbuHassan 83
Practical Applications of Generators
● Use Cases:
● Lazy Evaluation: Only generating
values when needed.
● State Machines: Modeling state
transitions with generators.
● Asynchronous Control Flow: Managing
async operations in a linear, readable
way.
11/30/2024 Dr. Amjad AbuHassan 84
Handling Errors in Generators
● Using try...catch Inside Generators:
11/30/2024 Dr. Amjad AbuHassan 85
Handling Errors in Generators cont.
● Throwing Errors into Generators:
11/30/2024 Dr. Amjad AbuHassan 86
Generators and Recursion
● Recursive Generators:
Generators can call
themselves recursively.
● Use Cases: Useful for tree
traversal, graph algorithms,
and hierarchical data
processing.
11/30/2024 Dr. Amjad AbuHassan 89
Comparing Generators and Async/Await
● Generators:
● Can pause and resume execution.
● Used for custom iteration, state management, and async control.
● Async/Await:
● Simplifies asynchronous code using Promises.
● Preferred for modern async programming.
● When to Use:
● Generators: When fine-grained control over execution is needed.
● Async/Await: For straightforward async operations.
11/30/2024 Dr. Amjad AbuHassan 91
Higher-Order Functions
11/30/2024 Dr. Amjad AbuHassan 96
Introduction
● A higher-order function is a function that meets at least one of the following
criteria:
● Takes one or more functions as arguments.
● Returns a function as its result.
● By contrast, functions that do neither are called first-order functions.
● Why Use Higher-Order Functions?
● Abstraction, Reusability, Composability, Functional Programming .. Etc.
11/30/2024 Dr. Amjad AbuHassan 97
Functions Taking Other Functions as
Arguments
● JavaScript arrays have several built-in higher-order functions, such as map, filter,
reduce, forEach, and sort.
11/30/2024 Dr. Amjad AbuHassan 98
Functions Taking Other Functions as
Arguments cont.
11/30/2024 Dr. Amjad AbuHassan 99
Functions Returning Other Functions
● The makeMultiplier function returns a new function that multiplies its input by a
specified multiplier.
11/30/2024 Dr. Amjad AbuHassan 100
Common Use Cases (Callbacks)
● A function passed into another function as an argument to be executed later.
11/30/2024 Dr. Amjad AbuHassan 101
Function Composition
● Combining functions to create new functions.
11/30/2024 Dr. Amjad AbuHassan 102
Using Array Methods with Arrow Functions
11/30/2024 Dr. Amjad AbuHassan 103
Higher-Order Functions in Asynchronous
Programming
11/30/2024 Dr. Amjad AbuHassan 104
Currying
● Transforming a function with multiple arguments into a sequence of nested
functions, each taking a single argument.
11/30/2024 Dr. Amjad AbuHassan 105
Example: Creating a Function that Filters
Arrays
11/30/2024 Dr. Amjad AbuHassan 106
this Keyword
11/30/2024 Dr. Amjad AbuHassan 107
Introduction
● The this keyword in JavaScript is a fundamental concept that can be both powerful
and confusing.
● It refers to an object that is executing the current piece of code.
● What Is this in JavaScript?
● Contextual Reference: The value of this is determined by how a function is called
(runtime binding), not where or how the function is defined.
● Dynamic Nature: Unlike some other programming languages, this in JavaScript can
change based on the context in which a function is invoked.
11/30/2024 Dr. Amjad AbuHassan 108
this value
The value of this varies depending on the execution context:
● Global Context (Default Binding)
● Function Context
● Method Context
● Constructor Functions (new Binding)
● Explicit Binding (call, apply, bind)
● Arrow Functions
● Event Handlers
11/30/2024 Dr. Amjad AbuHassan 109
The this Keyword
● Definition: Refers to the
object that is currently
executing the function.
● Context: Determined by how
a function is called.
11/30/2024 Dr. Amjad AbuHassan 110
this in Different Contexts
● Global Context: Refers to the global object (window in browsers).
● Function Context: Depends on how the function is called.
11/30/2024 Dr. Amjad AbuHassan 111
this in Different Contexts cont.
● Constructor Context: Refers to the new instance being created.
11/30/2024 Dr. Amjad AbuHassan 112
Arrow Functions and this
● Lexical this: Arrow functions do
not have their own this context.
● Inherits this: Arrow functions
inherit this from the surrounding
scope.
11/30/2024 Dr. Amjad AbuHassan 113
Handling this in Callbacks
● Using bind: Explicitly bind this to a function.
11/30/2024 Dr. Amjad AbuHassan 114
Handling this in Callbacks cont.
● Using Arrow Functions: Lexically binds this.
11/30/2024 Dr. Amjad AbuHassan 115