Javascript
This is a collection of notes on Javascript. This is a work in progress and will be updated regularly.
- 00. Introduction to Javascript
- 01. Basics of Javascript
- 02. Values, Types, and Operators
- 03. Objects and arrays
- 04. Functions
- 05. Handling events
00. Introduction to Javascript
Notes on Javascript
JavaScript is a scripting language you can use to make web pages interactive. It is one of the core technologies of the web, along with HTML and CSS, and is supported by all modern browsers.
Why Learn JavaScript?
JavaScript is among the most powerful and flexible programming languages of the web. It powers the dynamic behavior on most websites, including this one.
JavaScript can be extended for a variety of purposes by supplementing it with additional objects; for example:
Client-side JavaScript extends the core language by supplying objects to control a browser and its Document Object Model (DOM). For example, client-side extensions allow an application to place elements on an HTML form and respond to user events such as mouse clicks, form input, and page navigation.
Server-side JavaScript extends the core language by supplying objects relevant to running JavaScript on a server. For example, server-side extensions allow an application to communicate with a database, provide continuity of information from one invocation to another of the application, or perform file manipulations on a server.
JavaScript and the ECMAScript specification
JavaScript is standardized at Ecma International — the European association for standardizing information and communication systems (ECMA was formerly an acronym for the European Computer Manufacturers Association) to deliver a standardized, international programming language based on JavaScript. This standardized version of JavaScript, called ECMAScript, behaves the same way in all applications that support the standard.
ECMAScript 6 It is the sixth edition of the ECMA-262 standard, and features major changes and improvements to the ECMAScript specification.
This edition of ECMAScript changed its name from ES6 to ES2015 because in 2015 Ecma International decided to switch to annual releases of ECMAScript. Accordingly, Ecma International also started to name new editions of the ECMAScript specification based on the year they are released. In short, ES6 and ES2015 are two different names for the same thing.
Babel A transpiler that can convert ES6 code to ES5 code.
Edge and Internet Explorer do not fully support features from the ES6 specification.
Reference
01. Basics of Javascript
We think we are creating the system for our own purposes. We believe we are making it in our own image... But the computer is not really like us. It is a projection of a very slim part of ourselves: that portion devoted to logic, order, rule, and clarity. - Ellen Ullman, Close to the Machine: Technophilia and its Discontents
What is JavaScript?
one thread == one call stack == one thing at a time
JavaScript was introduced in 1995 as a way to add programs to web pages in the Netscape Navigator browser. The language has since been adopted by all other major graphical web browsers. It has made modern web applications possible—applications with which you can interact directly without doing a page reload for every action. JavaScript is also used in more traditional websites to provide various forms of interactivity and cleverness.
After its adoption outside of Netscape, a standard document was written to describe the way the JavaScript language should work so that the various pieces of software that claimed to support JavaScript were actually talking about the same language. This is called the ECMAScript standard, after the Ecma International organization that did the standardization. In practice, the terms ECMAScript and JavaScript can be used interchangeably —they are two names for the same language.
A JavaScript engine
A program or interpreter that understands and executes JavaScript code.
Synonyms: JavaScript interpreter, JavaScript implementation
JavaScript engines are commonly found in web browsers, including V8 in Chrome, SpiderMonkey in Firefox, and Chakra in Edge. Each engine is like a language module for its application, allowing it to support a certain subset of the JavaScript language.
A JavaScript engine to a browser is like language comprehension to a person. If we re-visit our example of the actions “walk”, “run”, “jump”, a JavaScript engine is the part of an “entity” that actually understands what these actions mean.
A JavaScript runtime
The environment in which the JavaScript code runs and is interpreted by a JavaScript engine.The runtime provides the host objects that JavaScript can operate on and work with.
Synonyms: Host environment
Have you ever worked with the window or document host objects? The window and document objects are not actually a part of the core JavaScript language. They are Web APIs, objects provided by a browser acting as JavaScript’s host environment. For the server side, the JavaScript runtime is Node.js. Server-related host objects such as the file system, processes, and requests are provided in Node.js.
An interesting point: different JavaScript runtimes can share the same JavaScript engine. V8, for example, is the JavaScript engine used in both Google Chrome and Node.js — two very different environments.
Comments
Comments are lines of code that JavaScript will intentionally ignore. Comments are a great way to leave notes to yourself and to other people who will later need to figure out what that code does.
There are two ways to write comments in JavaScript:
// Single line comment
/* for multi line comment */
Comments are mostly used to document the code for easy understading.
Reference:
-
https://www.freecodecamp.org/news/whats-the-difference-between-javascript-and-ecmascript-cba48c73a2b5/
-
https://github.com/lydiahallie/javascript-questions
-
https://eloquentjavascript.net/00_intro.html
02. Values, Types, and Operators
We will look at four types of JavaScript values in this chapter: numbers, strings, Booleans, and undefined values.
Below the surface of the machine, the program moves. Without effort, it expands and contracts. In great harmony, electrons scatter and regroup. The forms on the monitor are but ripples on the water. The essence stays invisibly below. - Master Yuan-Ma, The Book of Programming
Inside the computer’s world, there is only data. You can read data, modify data, create new data. All this data is stored as long sequences of bits and is thus fundamentally same.
Bits are any kind of two-valued things, usually described as zeros and ones.
Values
Chunks of bits are called values. Every value has a type that determines its role. Some values are numbers, some values are pieces of text, some values are functions, and so on.
To create a value, you must merely invoke its name.
Value Types
Numbers
Values of the number type are numeric values.
Ex: 13
Use that in a program, and it will cause the bit pattern for the number 13 to come into existence inside the computer’s memory.
JavaScript uses a fixed number of bits, 64 of them, to store a single number value.
Fractional numbers are written by using a dot.
9.81
For very big or very small numbers, you may also use scientific notation by adding an e (for exponent), followed by the exponent of the number.
2.998e8
That is 2.998 × 108 = 299,800,000.
Calculations with whole numbers (also called integers) smaller than the aforementioned 9 quadrillion are guaranteed to always be precise. Unfortunately, calculations with fractional numbers are generally not. Just as π (pi) cannot be precisely expressed by a finite number of decimal digits, many numbers lose some precision when only 64 bits are available to store them
Arithmetic
The main thing to do with numbers is arithmetic. Arithmetic operations such as addition or multiplication take two number values and produce a new number from them.
Ex:
The +
and *
symbols are called operators. When operators appear together without parentheses, the order in which they are applied is determined by the precedence of the operators.
Special numbers
- Infinity
The first two are Infinity and -Infinity, which represent the positive and negative infinities.
- NaN
NaN stands for “not a number”, even though it is a value of the number type.
When you try to calculate 0 / 0
(zero divided by zero), Infinity - Infinity
, or any number of other numeric operations you will be NaN.
Strings
Strings are used to represent text. They are written by enclosing their content in quotes.
You can use single quotes, double quotes, or backticks to mark strings, as long as the quotes at the start and the end of the string match.
Newlines (the characters you get when you press enter) can be included without escaping only when the string is quoted with backticks (`).
whenever a backslash () is found inside quoted text, it indicates that the character after it has a special meaning. This is called escaping the character.
When an n character occurs after a backslash, it is interpreted as a newline. Similarly, a t after a backslash means a tab character.
Many emoji take up two “character positions” in JavaScript strings.
Strings cannot be divided, multiplied, or subtracted, but the + operator can be used on them to concatenate two strings.
Ex:
The following line will produce the string "concatenate"
Backtick-quoted strings, usually called template literals, can do a few more tricks.
When you write something inside $ in a template literal, its result will be computed, converted to a string, and included at that position. The example produces “half of 100 is 50”.
Empty values
There are two special values, written null and undefined, that are used to denote the absence of a meaningful value.
Short-circuiting of logical operators
The logical operators && and || handle values of different types in a peculiar way. They will convert the value on their left side to Boolean type in order to decide what to do, but depending on the operator and the result of that conversion, they will return either the original left-hand value or the right-hand value.
Type coercion
true
and false
are Boolean values. To coerce a value into a boolean means to take any value that is NOT true or false and try to convert it to either of those. In JavaScript, you can easily check what the outcome of any value is when coerced into a Boolean by typing: Boolean(value)
.
You can see that some values evaluate to true and others to false. These values are usually called truthy and falsy values.
||
operator:
will return the value to its left when that can be converted to true and will return the value on its right otherwise.
Practical application:
In React application:
Examples of expressions that can be converted to false are:
- null;
- NaN;
- 0;
- empty string ("" or '' or ``);
- undefined.
while all the other values count as true.
Logical AND (&&) operator:
In a chain of &&s, each value will be evaluated from left to right. If any of these values happen to be falsy, that value will be returned and the chain will not continue.
Null safety operator ( ? ):
?. is a null safety operator, returns undefined if property is non-existent.
Assigning values
you can store a value in a variable with the assignment operator (=).
Initializing varialbes with value
Understanding Uninitialized Variables
When variables are declared, they have an initial value of undefined. If you do a mathematical operation on an undefined variable your result will be NaN which means "Not a Number". If you concatenate a string with an undefined variable, you will get a literal string of undefined.
Write variable names in JavaScript in camelCase. In camelCase, multi-word variable names have the first word in lowercase and the first letter of each subsequent word is capitalized.
const
and let
are block scoped and var
is global scoped.
when we create a variable using var we see it in global context and for let and scope it is not
closes function along with lexical scope
Summary
We looked at four types of JavaScript values in this chapter: numbers, strings, Booleans, and undefined values.
Such values are created by typing in their name (true, null) or value (13, "abc"). You can combine and transform values with operators. We saw binary operators for arithmetic (+, -, *, /, and %), string concatenation (+), comparison (==, !=, ===, !==, <, >, <=, >=), and logic (&&, ||
), as well as several unary operators (- to negate a number, ! to negate logically, and typeof to find a value’s type) and a ternary operator (?:) to pick one of two values based on a third value.
Reference:
-
https://www.freecodecamp.org/news/whats-the-difference-between-javascript-and-ecmascript-cba48c73a2b5/
-
https://github.com/lydiahallie/javascript-questions
-
https://eloquentjavascript.net/01_values.html
-
https://medium.com/@nicolasmarcora/mastering-javascripts-and-logical-operators-fd619b905c8f
03. Objects and arrays
Understanding objects and arrays in javascript
Objects
In JavaScript, almost "everything" is an object.
- Booleans can be objects (if defined with the new keyword)
- Numbers can be objects (if defined with the new keyword)
- Strings can be objects (if defined with the new keyword)
- Dates are always objects
- Maths are always objects
- Regular expressions are always objects
- Arrays are always objects
- Functions are always objects
- Objects are always objects
It is a common practice to declare objects with the const keyword.
JavaScript objects are containers for named values, called properties and methods.
Properties
The named values, in JavaScript objects, are called properties.
Almost all JavaScript values have properties. The exceptions are null
and undefined
.
Accessing properties
- Using dot notation (.)
When using a dot, the word after the dot is the literal name of the property.
- Array like notation ([])
When using square brackets, the expression between the brackets is evaluated to get the property name.
Methods
Methods are actions that can be performed on objects.
Object properties can be both primitive values, other objects, and functions.
An object method is an object property containing a function definition.
Arrays
JavaScript provides a data type specifically for storing sequences of values. It is called an array and is written as a list of values between square brackets, separated by commas.
Array Objects
function bookInfo( name, author, pubDate) {
this.name = name;
this.author = author;
this.date = pubDate;
}
var book = new Array();
book[0] = new bookInfo("Jane Eyre", "C. Bronte", "1847");
book[1] = new bookInfo("The Stranger", "A. Camus", "1942");
book[2] = new bookInfo("Oliver Twist", "C. Dickens", "1846");
book[3] = new bookInfo("Rebecca", "D. DuMaurier", "1938");
book[4] = new bookInfo("Stranger in a Strange Land", "R. Heinlein", "1961");
Mutability
Mutable is a type of variable that can be changed. In JavaScript, only objects and arrays are mutable, not primitive values.
You can make a variable name point to a new value, but the previous value is still held in memory.
A mutable object is an object whose state can be modified after it is created.
Immutables are the objects whose state cannot be changed once the object is created.
Strings and Numbers are Immutable. Lets understand this with an example:
On appending the "immutableString" with a string value, following events occur:
- Existing value of "immutableString" is retrieved
- "World" is appended to the existing value of "immutableString"
- The resultant value is then allocated to a new block of memory
- "immutableString" object now points to the newly created memory space
- Previously created memory space is now available for garbage collection.
Prototype Property
JavaScript is often described as a prototype-based language — to provide inheritance, objects can have a prototype object, which acts as a template object that it inherits methods and properties from.
An object's prototype object may also have a prototype object, which it inherits methods and properties from, and so on. This is often referred to as a prototype chain, and explains why different objects have properties and methods defined on other objects available to them.
All JavaScript objects inherit properties and methods from a prototype.
Date
objects inherit from Date.prototype
Array
objects inherit from Array.prototype
Person
objects inherit from Person.prototype
The Object.prototype
is on the top of the prototype inheritance chain:
Date
objects, Array
objects, and Person
objects inherit from Object.prototype
.
The JavaScript prototype property allows you to add new properties to object constructors:
Only modify your own prototypes. Never modify the prototypes of standard JavaScript objects.
Spread operators
Spread Operator (...) takes in an iterable (e.g an array) and expands it into individual elements.
Rest Operator
It can be useful for a function to accept any number of arguments. For example, Math.max computes the maximum of all the arguments it is given.
To write such a function, you put three dots before the function’s last parameter, like this:
When such a function is called, the rest parameter is bound to an array containing all further arguments. If there are other parameters before it, their values aren’t part of that array. When, as in max, it is the only parameter, it will hold all arguments.
Quiz
Everything in JavaScript is either a...
- A: primitive or object
- B: function or object
- C: trick question! only objects
- D: number or object
Answer
Answer: A
JavaScript only has primitive types and objects.
Primitive types are boolean
, null
, undefined
, bigint
, number
, string
, and symbol
.
What differentiates a primitive from an object is that primitives do not have any properties or methods; however, you'll note that 'foo'.toUpperCase()
evaluates to 'FOO'
and does not result in a TypeError
. This is because when you try to access a property or method on a primitive like a string, JavaScript will implicitly wrap the primitive type using one of the wrapper classes, i.e. String
, and then immediately discard the wrapper after the expression evaluates. All primitives except for null
and undefined
exhibit this behaviour.
What's the output?
- A:
true
false
true
- B:
false
false
true
- C:
true
false
false
- D:
false
true
true
Answer
Answer: C
new Number()
is a built-in function constructor. Although it looks like a number, it's not really a number: it has a bunch of extra features and is an object.
When we use the ==
operator, it only checks whether it has the same value. They both have the value of 3
, so it returns true
.
However, when we use the ===
operator, both value and type should be the same. It's not: new Number()
is not a number, it's an object. Both return false.
What happens when we do this?
- A: Nothing, this is totally fine!
- B:
SyntaxError
. You cannot add properties to a function this way. - C:
"Woof"
gets logged. - D:
ReferenceError
Answer
Answer: A
This is possible in JavaScript, because functions are objects! (Everything besides primitive types are objects)
A function is a special type of object. The code you write yourself isn't the actual function. The function is an object with properties. This property is invocable.
Which one is true?
- A:
mouse.bird.size
is not valid - B:
mouse[bird.size]
is not valid - C:
mouse[bird["size"]]
is not valid - D: All of them are valid
Answer
Answer: A
In JavaScript, all object keys are strings (unless it's a Symbol). Even though we might not type them as strings, they are always converted into strings under the hood.
JavaScript interprets (or unboxes) statements. When we use bracket notation, it sees the first opening bracket [
and keeps going until it finds the closing bracket ]
. Only then, it will evaluate the statement.
mouse[bird.size]
: First it evaluates bird.size
, which is "small"
. mouse["small"]
returns true
However, with dot notation, this doesn't happen. mouse
does not have a key called bird
, which means that mouse.bird
is undefined
. Then, we ask for the size
using dot notation: mouse.bird.size
. Since mouse.bird
is undefined
, we're actually asking undefined.size
. This isn't valid, and will throw an error similar to Cannot read property "size" of undefined
.
Which of the following will modify the person
object?
- A:
person.name = "Evan Bacon"
- B:
person.age = 21
- C:
delete person.name
- D:
Object.assign(person, { age: 21 })
Answer
Answer: A
With Object.seal
we can prevent new properies from being added, or existing properties to be removed.
However, you can still modify the value of existing properties.
Which of the following will modify the person
object?
- A:
person.name = "Evan Bacon"
- B:
delete person.address
- C:
person.address.street = "101 Main St"
- D:
person.pet = { name: "Mara" }
Answer
Answer: C
The Object.freeze
method freezes an object. No properties can be added, modified, or removed.
However, it only shallowly freezes the object, meaning that only direct properties on the object are frozen. If the property is another object, like address
in this case, the properties on that object aren't frozen, and can be modified.
What's the output?
- A:
[[1, 2, 3, 4, 5]]
- B:
[1, 2, 3, 4, 5]
- C:
1
- D:
[1]
Answer
Answer: C
We can unpack values from arrays or properties from objects through destructuring. For example:
The value of a
is now 1
, and the value of b
is now 2
. What we actually did in the question, is:
This means that the value of y
is equal to the first value in the array, which is the number 1
. When we log y
, 1
is returned.
What's the output?
- A:
123
- B:
456
- C:
undefined
- D:
ReferenceError
Answer
Answer: B
Object keys are automatically converted into strings. We are trying to set an object as a key to object a
, with the value of 123
.
However, when we stringify an object, it becomes "[object Object]"
. So what we are saying here, is that a["[object Object]"] = 123
. Then, we can try to do the same again. c
is another object that we are implicitly stringifying. So then, a["[object Object]"] = 456
.
Then, we log a[b]
, which is actually a["[object Object]"]
. We just set that to 456
, so it returns 456
.
What's the output?
- A:
Hello
- B:
Hey!
- C:
undefined
- D:
ReferenceError
- E:
TypeError
Answer
Answer: A
In JavaScript, all objects interact by reference when setting them equal to each other.
First, variable c
holds a value to an object. Later, we assign d
with the same reference that c
has to the object.
When you change one object, you change all of them.
All object have prototypes.
- A: true
- B: false
Answer
Answer: B
All objects have prototypes, except for the base object. The base object is the object created by the user, or an object that is created using the new
keyword. The base object has access to some methods and properties, such as .toString
. This is the reason why you can use built-in JavaScript methods! All of such methods are available on the prototype. Although JavaScript can't find it directly on your object, it goes down the prototype chain and finds it there, which makes it accessible for you.
What's the output?
- A:
TypeError
- B:
SyntaxError
- C:
Lydia Hallie
- D:
undefined
undefined
Answer
Answer: A
In JavaScript, functions are objects, and therefore, the method getFullName
gets added to the constructor function object itself. For that reason, we can call Person.getFullName()
, but member.getFullName
throws a TypeError
.
If you want a method to be available to all object instances, you have to add it to the prototype property:
What's the output?
- A:
"Just give Lydia pizza already!"
- B:
TypeError: not a function
- C:
SyntaxError
- D:
undefined
Answer
Answer: A
String
is a built-in constructor, which we can add properties to. I just added a method to its prototype. Primitive strings are automatically converted into a string object, generated by the string prototype function. So, all strings (string objects) have access to that method!
What's the output?
- A:
{ admin: true, user: { name: "Lydia", age: 21 } }
- B:
{ admin: true, name: "Lydia", age: 21 }
- C:
{ admin: true, user: ["Lydia", 21] }
- D:
{ admin: true }
Answer
Answer: B
It's possible to combine objects using the spread operator ...
. It lets you create copies of the key/value pairs of one object, and add them to another object. In this case, we create copies of the user
object, and add them to the admin
object. The admin
object now contains the copied key/value pairs, which results in { admin: true, name: "Lydia", age: 21 }
.
What's the output?
- A:
["banana", "apple", "pear", "orange"]
- B:
[["banana", "apple"], "pear", "orange"]
- C:
["banana", "apple", ["pear"], "orange"]
- D:
SyntaxError
Answer
Answer: D
...args
is a rest parameter. The rest parameter's value is an array containing all remaining arguments, and can only be the last parameter! In this example, the rest parameter was the second parameter. This is not possible, and will throw a syntax error.
The above example works. This returns the array [ 'banana', 'apple', 'orange', 'pear' ]
References:
-
https://eloquentjavascript.net/04_data.html
-
https://developer.mozilla.org/en-US/docs/Glossary/Mutable
-
https://github.com/lydiahallie/javascript-questions/blob/master/README.md
-
https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/Object_prototypes
-
http://latentflip.com/loupe/?code=JC5vbignYnV0dG9uJywgJ2NsaWNrJywgZnVuY3Rpb24gb25DbGljaygpIHsKICAgIHNldFRpbWVvdXQoZnVuY3Rpb24gdGltZXIoKSB7CiAgICAgICAgY29uc29sZS5sb2coJ1lvdSBjbGlja2VkIHRoZSBidXR0b24hJyk7ICAgIAogICAgfSwgMjAwMCk7Cn0pOwoKY29uc29sZS5sb2coIkhpISIpOwoKc2V0VGltZW91dChmdW5jdGlvbiB0aW1lb3V0KCkgewogICAgY29uc29sZS5sb2coIkNsaWNrIHRoZSBidXR0b24hIik7Cn0sIDUwMDApOwoKY29uc29sZS5sb2coIldlbGNvbWUgdG8gbG91cGUuIik7!!!PGJ1dHRvbj5DbGljayBtZSE8L2J1dHRvbj4%3D
04. Functions
How functions are used
Mapping
Functions map input arguments to return values, meaning that for each set of inputs, there exists an output. A function will take the inputs and return the corresponding output. procedures i/o˝
pure functions has no side effects
given same input produces same output
Not pure functions
Dependent on time random numbers
What is Functional Programming
Higher order functions
Functions that operate on other functions, either by taking them as arguments or by returning them, are called higher-order functions.
Higher-order functions allow us to abstract over actions, not just values.
Higher order components (HOC's)
References:
- https://www.smashingmagazine.com/2020/06/higher-order-components-react/
05. Handling events
You have power over your mind—not outside events. Realize this, and you will find strength. - Marcus Aurelius, Meditations
Some programs work with direct user input, such as mouse and keyboard actions. That kind of input isn’t available as a well-organized data structure—it comes in piece by piece, in real time, and the program is expected to respond to it as it happens.
Event Loop
Debouncing in Javascript
Debouncing is a programming practice used to ensure that time-consuming tasks do not fire so often, that it stalls the performance of the web page. In other words, it limits the rate at which a function gets invoked.
Throttle
In throttle we don’t allow to our function to execute more than once every X milliseconds.
References:
- https://css-tricks.com/debouncing-throttling-explained-examples/
- https://dev.to/iyashsoni/javascript-debounce-vs-throttle-392i
- https://codepen.io/akshaymarch7/pen/pXgxGo?editors=0011