JavaScript Flashcards
Deeply understand the JS language and the tools within it. (47 cards)
String bit storage in JS
In JavaScript, strings are fundamentally stored as a sequence of 16-bit unsigned integer values, representing UTF-16 code units. This means each character in a JavaScript string is typically represented by a minimum of 16 bits (2 bytes). These are called code units.
charCodeAt() vs codePointAt
JavaScript’s charCodeAt method gives you a code unit, not a full character code. The codePointAt method, added later, does give a full Unicode character, so we could use that to get characters from a string.
Number bit storage in JS
JavaScript stores numbers as 64-bit double-precision floating-point numbers, adhering to the IEEE 754 standard. This means each number occupies 64 bits of memory.
These 64 bits are allocated as follows:
Sign bit (1 bit): Indicates whether the number is positive or negative.
Exponent (11 bits): Represents the power of 2 that the mantissa is multiplied by.
Mantissa/Fraction (52 bits): Represents the significant digits of the number.
bit vs byte
A bit is the smallest unit of data in computing, representing a single binary value (0 or 1). A byte is a larger unit, typically consisting of 8 bits. Bytes are commonly used to represent characters, and are the standard unit for measuring storage capacity.
|| operator
|| (Logical OR)
Returns the first truthy value (or the last one if none are truthy).
Commonly used for default values.
const name = userName || “Guest”;
If userName is falsy (like null, undefined, ‘’, 0, false), “Guest” will be used.
&& operator
&& (Logical AND)
Returns the first falsy value (or the last one if none are falsy).
Commonly used for conditional execution.
isLoggedIn && showDashboard();
If isLoggedIn is truthy, showDashboard() runs.
?? operator
?? (Nullish Coalescing)
Returns the right-hand value only if the left is null or undefined.
Safer for defaulting when ‘’, 0, or false are valid values.
const count = inputCount ?? 10;
If inputCount is null or undefined, 10 is used. If it’s 0, 0 is kept — unlike ||.
unary vs binary operators
Unary and binary operators differ in the number of operands they act upon. Unary operators take one operand, while binary operators take two.
expression
An expression evaluates to a value
https://www.joshwcomeau.com/javascript/statements-vs-expressions/
statement
A statement performs an action or task
https://www.joshwcomeau.com/javascript/statements-vs-expressions/
declaration
A declaration introduces a name (like a variable) and associates it with a value or type.
function expression
The function keyword can be used to define a function inside an expression.
const getRectArea = function (width, height) {
return width * height;
};
function declaration
The function declaration creates a binding of a new function to a given name. Function declarations are not part of the regular top-to-bottom flow of control. They are conceptually moved to the top of their scope and can be used by all the code in that scope.
function calcRectArea(width, height) {
return width * height;
}
arrow function expression
An arrow function expression is a compact alternative to a traditional function expression, with some semantic differences and deliberate limitations in usage:
Arrow functions don’t have their own bindings to this, arguments, or super, and should not be used as methods.
Arrow functions cannot be used as constructors. Calling them with new throws a TypeError. They also don’t have access to the new.target keyword.
Arrow functions cannot use yield within their body and cannot be created as generator functions.
const multiply = (x, y) => { return x * y; };
const square = x => x * x;
const horn = () => console.log(“Toot”);
generator functions
The function* declaration creates a binding of a new generator function to a given name. A generator function can be exited and later re-entered, with its context (variable bindings) saved across re-entrances.
function* generator(i) {
yield i;
yield i + 10;
}
.repeat()
The repeat() method of String values constructs and returns a new string which contains the specified number of copies of this string, concatenated together.
lexical scoping
In lexical scoping, when you write a function or block, it remembers the variables that were in scope at the time and place it was defined, not when it is called.
x = 10
def foo():
print(x)
def bar():
x = 20
foo()
bar()
Under lexical scoping (e.g., in Python):
foo prints 10, because when foo was defined, x = 10 was in scope.
dynamic scoping
In dynamic scoping, variable lookup happens based on the call stack at runtime, not based on where the code appears in the file.
x = 10
def foo():
print(x)
def bar():
x = 20
foo()
bar()
Under dynamic scoping:
foo prints 20, because bar() was the caller of foo, and bar() had x = 20.
How Does the Call Stack Work?
JavaScript operates in a single-threaded environment, meaning that it can only execute one operation at a time. The Call Stack in JavaScript manages the order of function execution, handling nested calls and recursion. It ensures functions run in the correct sequence and are properly returned to after execution. Improper use, like infinite recursion, can lead to a stack overflow. Understanding it is key to maintaining efficient program flow.
Function Call, Executing the Function, Nested Function Calls, Returning from a Function, Completion of Program
https://www.geeksforgeeks.org/javascript/what-is-the-call-stack-in-javascript/
closures
A closure is the combination of a function bundled together (enclosed) with references to its surrounding state (the lexical environment). In other words, a closure gives a function access to its outer scope. In JavaScript, closures are created every time a function is created, at function creation time.
function makeAdder(x) {
return function (y) {
return x + y;
};
}
const add5 = makeAdder(5);
const add10 = makeAdder(10);
console.log(add5(2)); // 7
console.log(add10(2)); // 12
add5 and add10 both form closures. They share the same function body definition, but store different lexical environments. In add5’s lexical environment, x is 5, while in the lexical environment for add10, x is 10.
Math.abs()
The Math.abs() static method returns the absolute value of a number.
isNaN(undefined);
true
The original isNaN function was a mistake, and Number.isNaN should be preferred in all circumstances.
Number.isNaN(undefined);
false
The original isNaN function was a mistake, and Number.isNaN should be preferred in all circumstances.
Object.assign()
The Object.assign() static method copies all enumerable own properties from one or more source objects to a target object. It returns the modified target object. It does not create a new object; instead, it mutates the target directly and then returns that same target object.
const target = { a: 1, b: 2 };
const source = { b: 4, c: 5 };
const returnedTarget = Object.assign(target, source);
console.log(target);
// Expected output: Object { a: 1, b: 4, c: 5 }
console.log(returnedTarget === target);
// Expected output: true