chore (curriculum) add js fundamental review module transcripts (#58802)

This commit is contained in:
Hillary Nyakundi
2025-02-24 17:10:52 +03:00
committed by GitHub
parent f9b8efdaeb
commit dc9eeb3ffa
8 changed files with 471 additions and 8 deletions

View File

@@ -8,7 +8,31 @@ dashedName: what-is-a-string-object-and-how-does-it-differ-from-string-primitive
# --description--
Watch the video lecture and answer the questions below.
Watch the video or read the transcript and answer the questions below.
# --transcript--
What is a string object, and how does it differ from a string primitive in JavaScript?
In previous modules you have been used to working with strings literals like this:
```js
const greeting = "Hello, World!";
```
But JavaScript also has string objects. Both string objects and string primitives are used to handle text but they function differently under the hood. A string object is created using the string constructor function, which wraps the primitive value in an object. Here is how you would create a string object:
```js
const greetingObject = new String("Hello, World!");
console.log(typeof greetingObject); // "object"
```
When we use the `typeof` operator we can see that the result is of type object instead of type string. One of the things that you might have been wondering about is how you can use properties like the `.length` property on string primitives.
When you use the `length` property on a string primitive, JavaScript temporarily wraps the string primitive in a string object, to perform the operation. This is why you can use the `length` property and the different methods like `repeat()`, `concat()`, and `slice()`. These types of methods and properties are referred to as instance methods also properties and static methods. You will learn about how that works in detail in future modules.
One key difference between a string object and a string primitive is how it relates to memory and performance. String primitives are usually more memory efficient and faster compared to string objects. Although you will primarily work with string primitives in your code, it's still useful to understand how string objects work.
# --questions--

View File

@@ -8,7 +8,52 @@ dashedName: what-is-the-tostring-method-and-how-does-it-work
# --description--
Watch the lecture video and answer the questions below.
Watch the video or read the transcript and answer the questions below.
# --transcript--
What is the `toString()` method and how does it work?
The `toString()` method is a fundamental feature in JavaScript that converts a value to its string representation. It's a method you can use for numbers, booleans, arrays, and objects. One of the most common uses of `toString()` is to convert a number to its string representation. Here's an example:
```js
const num = 10;
console.log(num.toString()); // "10"
```
This method accepts an optional radix which is a number from `2` to `36`. This radix represents the base, such as base 2 for binary or base 8 for octal. If the radix is not specified it defaults to base 10, which is decimal. Here's an example of passing `2` as an argument to the `toString()` method:
```js
const num = 10;
console.log(num.toString(2)); // "1010"
```
The result will be `1010` which is the binary representation for the decimal number `10`.
You can also use the `toString()` method to convert arrays and objects to strings. Arrays have a custom implementation of `toString()` that converts each element to a string and joins them with commas. Here's an example:
```js
const arr = [1, 2, 3];
console.log(arr.toString()); // "1,2,3"
```
In this example all the elements of the array are joined together to form the string `1,2,3`.
When `toString()` method is used with objects, the result will not be a stringified version of the object properties.
```js
const person = {
name: "John",
age: 30,
isStudent: true
},
console.log(person.toString()); // "[object Object]"
```
In this example, the result will be the default string representation for the object which is `[object Object]`. To get a stringified version of the `person` object properties you'll need to use `JSON.stringify()` which you will learn about more in the future lecture videos.
In conclusion, the `toString()` method is used for converting values to strings. Understanding how it works with different data types and how to customize it for your own objects can greatly advance your ability to manipulate and display data in your JavaScript applications.
# --questions--

View File

@@ -8,7 +8,85 @@ dashedName: what-is-the-number-constructor-and-how-does-it-work-for-type-coercio
# --description--
Watch the lecture video and answer the questions below.
Watch the video or read the transcript and answer the questions below.
# --transcript--
What is the `Number()` constructor and how does it work for type coercion?
The `Number()` constructor is used to create a number object. The number object contains a few helpful properties and methods like the `isNaN` and the `toFix` method. Here's an example using the `Number()` constructor with the `new` keyword:
```js
const myNum = new Number("34");
console.log(typeof myNum); // "object"
```
In this example we pass in a string literal to the `Number()` constructor and the return type is of type `object` instead of a `string`.
When the `Number()` constructor is called as a function without the `new` keyword, then the return value will be the primitive number type. Most of the time you will be using the `Number()` constructor to convert other data types to the number data type. Here's an example of converting a string to a number:
```js
const myNum = Number("100");
console.log(myNum); // 100
console.log(typeof myNum); // number
```
This is helpful when you are getting input from the user and you need to convert that string input to a number so you can perform mathematical calculations.
If you try to call the `Number()` constructor through an empty string then the result will be the number `0`:
```js
const num = Number("");
console.log(num); // 0
```
This is because JavaScript will try to parse the string and since it doesn't contain any digits, the result will be zero.
If you try to pass in a string with random characters then the result will be `NaN` or "Not a Number".
```js
const num = Number("random");
console.log(num); // NaN
```
When working with booleans, `true` returns `1` because `true` gets converted to one and `false` returns `0` because `false` is converted to zero.
```js
const boolTrue = Number(true);
const boolFalse = Number(false);
console.log(boolTrue); // 1
console.log(boolFalse); // 0
```
If you pass in `null`, the result will be `0` and if you pass `undefined`, the result will be `NaN`.
```js
const undefinedNum = Number(undefined);
const nullNum = Number(null);
console.log(undefinedNum); // NaN
console.log(nullNum); // 0
```
When working with arrays there are a few things to consider, an empty array will return `0`, an array with a single number will return that number, an array with multiple numbers returns `NaN`, and an array with strings will return `undefined`.
```js
const obj1 = Number({});
const obj2 = Number({2: 2});
const obj3 = Number({key: "val"});
const obj4 = Number({key: true});
console.log(obj1); // NaN
console.log(obj2); // NaN
console.log(obj3); // NaN
console.log(obj4); // NaN
```
When working with objects, the result is always `NaN`.
In conclusion, you'll mostly use the `Number()` constructor for type conversion more than creating a number or a number object.
# --questions--

View File

@@ -8,7 +8,114 @@ dashedName: what-are-some-common-practices-for-naming-variables-and-functions
# --description--
Watch the lecture video and answer the questions below.
Watch the video or read the transcript and answer the questions below.
# --transcript--
What are some common practices for naming variables and functions?
Naming variables and functions is an important aspect of writing clean, readable and maintainable code. Good naming practices makes your code self-documenting reducing the need for extensive comments and making it easier for other developers including your future self to understand your code.
Let's start with general naming conventions in JavaScript. In previous lecture videos you learned about using camel case for variable names. For boolean variables, it's a common practice to use prefixes such as `is`, `has`, or `can`. This immediately tells the reader that the variable is a boolean:
```js
let isLoading = true;
let hasPermission = false;
let canEdit = true;
```
For functions the name should clearly indicate what the function does. It's often helpful to start with a verb:
```js
function getUserData(){
/* ... */
}
function calculateTotal(){
/* ... */
}
function validateInput(){
/* ... */
}
```
For functions that return a boolean often called predicates, you can use the same `is`, `has`, or `can` prefixes:
```js
function isValidEmail(email) {
/* ... */
}
function hasRequiredFields(form) {
/* ... */
}
```
When you have functions that retrieve data it's common to start with the word `get`:
```js
function getProductDetails(productId) {
/* ... */
}
function getUserProfile(userId) {
/* ... */
}
```
When you have functions that set data it's common to start with the word `set`:
```js
function setUserPreferences(preferences) {
/* ... */
}
function setPageTitle(title) {
/* ... */
}
```
For event handler functions, you might prefix with `handle` or suffix with `handler`:
```js
function handleClick(){
/* ... */
}
function onSubmit(){
/* ... */
}
function keyPressHandler(){
/* ... */
}
```
An event handler is an action that happens after an event has happened like a button click. You will learn about that in future lecture videos.
When naming iterator variables and loops, it's common to use single letters like `i`, `j`, or `k`, but for nested loops or more complex iterations more descriptive names can be helpful:
```js
for (let i = 0; i < array.length; i++) {
/* ... */
}
for (let studentIndex = 0; studentIndex < students.length; studentIndex++) {
/* ... */
}
```
For array names consider using plural nouns to indicate that the variable contains multiple items:
```js
const colors = ['red', 'green', 'blue'];
const userNames = ['Alice', 'Bob', 'Charlie'];
```
Remember the goal is to make your code as self explanatory as possible. A good rule of thumb is that if you need to add a comment to explain what a variable or function does, you might want to consider renaming it to something more descriptive.
Lastly, be consistent with your codebase or team. If your team has established naming conventions, stick to them. Consistency makes the code more readable and maintainable for everyone involved.
# --questions--

View File

@@ -8,7 +8,58 @@ dashedName: how-do-you-get-the-length-for-an-array-and-how-can-you-create-an-emp
# --description--
Watch the lecture video and answer the questions below.
Watch the video or read the transcript and answer the questions below.
# --transcript--
How do you get the length for an array, and how can you create an empty array of fixed length?
In prior lecture videos you were first introduced to the `length` property, this property returns the number of elements in an array. So here is a quick reminder on how it works:
```js
const fruits = ['apple', 'banana', 'orange'];
console.log(fruits.length); // 3
```
It's possible to have arrays with empty slots. Empty slots are defined as slots with nothing in them. This is different than an array with the value of `undefined`. These types of arrays are known as sparse arrays. Here is an example:
```js
const sparseArray = [1, , , 4];
console.log(sparseArray.length); // 4
```
In this case even though we only have two defined elements, `1` and `4`. The length is `4` because the highest index (`3`) plus `1` gives us a length of `4`.
Now let's discuss how to create an empty array of fixed length. There are few ways to do this in JavaScript but one common method is to use the `Array()` constructor with a numeric argument. The `Array()` constructor can be used with the `new` keyword to create a new array. Here is an example:
```js
const emptyArray = new Array(5);
console.log(emptyArray.length); // 5
console.log(emptyArray); // [,,,,]
```
In this example, we create a new array using the `Array(5)`. This creates a sparse array with a length of `5` where all the slots are empty.
Another way to create an empty array of fixed length is to use the `Array.from()` method with a length argument. This method creates an array of the specified length with all elements initialized to `undefined`:
```js
const fixedLengthArray = Array.from({ length: 5 });
console.log(fixedLengthArray.length); // 5
// [undefined, undefined, undefined, undefined, undefined]
console.log(fixedLengthArray);
```
If you want to create an array of specific length and fill it with a default value, you can use the `Array.fill()` method:
```js
const filledArray = new Array(3).fill(0);
console.log(filledArray); // [0, 0, 0]
```
This creates an array of length three and fills all elements with the value `0`.
Understanding how to get the length of an array and create arrays of fixed length is important for many programming tasks especially when you need to initialize arrays for specific algorithms or data structures.
# --questions--

View File

@@ -8,7 +8,55 @@ dashedName: what-are-linters-and-formatters-and-how-can-they-help-you-with-code-
# --description--
Watch the lecture video and answer the questions below.
Watch the video or read the transcript and answer the questions below.
# --transcript--
What are linters and formatters, and how can they help you with code consistency?
In the world of software development maintaining clean, consistent and error-free code is important. This is where linters and formatters come into play. These tools are essential for developers to ensure code quality and consistency across a projects and teams.
Let's start with linters. A linter is a static code analysis tool that flags programming errors, bugs, stylistic errors, and suspicious constructs. The term lint comes from a Unix utility that examines C language source code.
Today linters exist for most programming languages including JavaScript. Linters help in several ways. First they catch potential errors before runtime. For example, a linter might flag the use of undefined variable or a function being called with the wrong number of arguments. They also enforce coding standards and best practices. This might include rules about indentation, the use of semicolons, or the maximum allowed line length. Lastly, they help maintain consistency across a codebase especially when multiple developers are working on the same project.
A popular linter for JavaScript is ESLint. Here is a simple example of what ESLint might flag:
```js
function doSomething(x) {
return x + z
}
```
In this code variable `z` is not declared, so ESLint would flag the error `z` is not defined. Also, the last statement is missing a semicolon which ESLint might also flag in the code editor.
Formatters on the other hand are tools that automatically format your code to adhere to a specific style guide. While linters can often autofix some issues, formatters are specifically designed to rewrite your code to match a predetermined style.
Formatters ensure a consistent code style across an entire project or team regardless of individual developer preferences. They also save time and mental energy that would otherwise be spent on manual formatting. Lastly, they can make code reviews more efficient by eliminating discussions about code style.
A popular formatter for JavaScript is Prettier. Here is an example of how Prettier might format code. Here's a before formatting:
```js
function longFunction(
argument1,
argument2,
argument3
) {return argument1 + argument2 + argument3;}
```
And then after the prettier formatting:
```js
function longFunction(argument1, argument2, argument3) {
return argument1 + argument2 + argument3;
}
```
Both linters and formatters can be integrated into your development workflow in various ways. They can be included in your build process or added as plugins to your text editor or IDE providing real-time feedback as you code. Using linters and formatters together can significantly improve code quality and consistency. For example, you might use ESLint to catch potential errors and enforce certain coding practices, and then use Prettier to handle all formatting tasks.
Many developement teams set up these tools as part of their project configuration often with pre-commit hooks that run the linter and formatter before allowing code to be committed. This ensures that all code in the repository meets the teams standards for quality and style.
In summary, linters and formatters are powerful tools that help maintain code quality, catch potential errors early, and ensure consistency across codebases. By automating this aspects of code review they allow developers to focus more on solving problems and less on debating code style.
# --questions--

View File

@@ -8,7 +8,41 @@ dashedName: what-is-memory-management-and-how-does-it-work-in-javascript
# --description--
Watch the lecture video and answer the questions below.
Watch the video or read the transcript and answer the questions below.
# --transcript--
What is memory management, and how does it work in JavaScript?
Memory management is an essential concept in programming, but it can be a bit confusing for beginners, let's break it down in simple terms.
When you run a program, including JavaScript code in a web browser, it needs memory to store all the information its working with. This includes varibles, functions, objects, basically everything your code creates and uses. Memory management is the process of controlling this memory, allocating it when needed, and freeing it up when it's no longer needed. In some programming languages, developers have to manually manage memory. They need to explicitly tell the computer when to allocate memory for new things and when to free up memory that's no longer needed. This can be powerful but also tricky as for getting to free memory can lead to memory leaks.
JavaScript however uses automatic memory management. This means that JavaScript (more specifically the JavaScript engine in your web browser) takes care of memory allocation and deallocation for you. You don't have to explicitly free memory in your code. This automatic process is often called garbage collection.
Here's how it works in simple terms. First allocation happens when you create a variable, objects or functions in your JavaScript code, memory is automatically allocated to store them. Then you use this allocated memory when you work with these variables, objects or functions in your code.
The JavaScript engine has clever ways to figure out when something in memory is no longer needed. Generally if there is no way for your program to access or use a piece of data any more it's considered no longer needed. Periodically the garbage collector runs, it finds a memory that's no longer needed and frees it up, making it available for future use. This process happens automatically which is great because it means you don't have to worry about managing memory yourself.
However, it's still important to understand this concept because you can sometimes accidentally keep references to things you don't need anymore preventing the garbage collector from freeing that memory. For example:
```js
function createLargeArray() {
let largeArray = new Array(1000000);
return function() {
console.log(largeArray.length);
};
}
let printArrayLength = createLargeArray();
printArrayLength();
```
In this code, even after `createLargeArray` finishes running, `largeArray` can't be garbage collected because the returned function still has access to it. This is a closure, and while closures are useful they can sometimes lead to more memory usage than you might expect. You will learn more about closures in future lecture videos.
As a beginner, you don't need to worry too much about the intricacies of memory management. JavaScript's automatic garbage collection takes care of most things for you. However, as you advance in your JavaScript journey, understanding these concepts can help you write more efficient code, especially for larger applications or when working with limited resources.
Remember, good coding practices, like avoiding global variables when possible and being mindful of what your functions are closing over, can help the JavaScript engine manage memory more efficiently.
# --questions--

View File

@@ -8,7 +8,83 @@ dashedName: what-are-closures-and-how-do-they-work
# --description--
Watch the lecture video and answer the questions below.
Watch the video or read the transcript and answer the questions below.
# --transcript--
What are closures, and how do they work?
Closures are one of the most powerful and often misunderstood features in JavaScript. At its core, a closure is a function that has access to variables in its outer enclosing lexical scope, even after the outer function has returned. This might sound complex but it's a fundamental concept that enables many advanced programming patterns in JavaScript.
To understand closures, let's start with an example:
```js
function outerFunction(x) {
let y = 10;
function innerFunction(){
console.log(x + y);
}
return innerFunction;
}
let closure = outerFunction(5);
closure(); // Output: 15
```
In this example, `outerFunction` takes a parameter `x` and defines a local variable `y`. It then defines an `innerFunction` that uses both `x` and `y`. Finally it returns `innerFunction`. When we call `outerFunction(5)` it returns `innerFunction` which we assign to the variable `closure`. When we later call `closure()` it still has access to `x` and `y` from `outerFunction` even though `outerFunction` has already finished executing. This is the essence of a closure.
The inner function maintains a reference to its outer lexical environment, preserving access to the variables in that environment even after the outer function has completed.
Closures are particularly useful for creating private variables and functions. Consider this example:
```js
function createCounter() {
let count = 0;
return function () {
count++;
return count;
};
}
let counter = createCounter();
console.log(counter()); // Output: 1
console.log(counter()); // Output: 2
```
In this case, `createCounter` returns a function that increments and returns a `count` variable. The `count` variable is not directly accessible from outside `createCounter`, but the returned function (our closure) has access to it. Each time we call `counter()`, it increments and returns the `count`.
Closures can also capture multiple variables from their outer scope. For example:
```js
function multiply(x) {
return function (y) {
return x * y;
};
}
let double = multiply(2);
console.log(double(5)); // Output: 10
```
Here the inner function captures the `x` parameter from `multiply`. When we create `double` by calling `multiply(2)` it returns a function that always multiplies its argument by `2`.
One important thing to note about closures is that they capture variables, by refrerence not by value. This means if the value of a captured variable changes, the closure will see the new value. For example:
```js
function createIncrementer() {
let count = 0;
return function () {
count++;
console.log(count);
};
}
let increment = createIncrementer();
increment(); // Output: 1
increment(); // Output: 2
```
Each time we call `increment` its working with the same `count` variable, not a copy of it's initial value. Closures are a powerful tool in JavaScript. as you continue to work with JavaScript you'll find that understanding and using closures effectively can greatly enhance your ability to write clean, efficient and powerful code.
# --questions--