diff --git a/packages/quiz/questions/what-are-the-differences-between-es6-class-and-es5-function-constructors/en-US.mdx b/packages/quiz/questions/what-are-the-differences-between-es6-class-and-es5-function-constructors/en-US.mdx index d27e506ef..442c672b8 100644 --- a/packages/quiz/questions/what-are-the-differences-between-es6-class-and-es5-function-constructors/en-US.mdx +++ b/packages/quiz/questions/what-are-the-differences-between-es6-class-and-es5-function-constructors/en-US.mdx @@ -2,6 +2,10 @@ title: What are the differences between ES2015 class and ES5 function constructors? --- +## TL;DR + +ES6 introduces a new way of creating classes, which provides a more intuitive and concise way to define and work with objects and inheritance compared to the ES5 function constructor syntax. + Let's first look at example of each: ```js @@ -45,3 +49,188 @@ class Student extends Person { ``` It's much more verbose to use inheritance in ES5 and the ES2015 version is easier to understand and remember. + +### Comparison of ES6 Class and ES5 Function constructor + +| Feature | ES5 Function Constructor | ES6 Class | +| --- | --- | --- | +| Syntax | Uses function constructors and prototypes | Uses `class` keyword | +| Constructor | Function with properties assigned using `this` | `constructor` method inside the class | +| Method Definition | Defined on the prototype | Defined inside the class body | +| Static Methods | Added directly to the constructor function | Defined using the `static` keyword | +| Inheritance | Uses `Object.create()` and manually sets prototype chain | Uses `extends` keyword and `super` function | +| Readability | Less intuitive and more verbose | More concise and intuitive | + +--- + +## ES5 Function constructor vs ES6 Classes + +ES6 classes and ES5 function constructors are two different ways of defining `classes` in JavaScript. They both serve the same purpose, but they have different syntax and behavior. + +### ES5 Function Constructor + +In ES5, you define a class-like structure using a function constructor and prototypes. Here’s an example: + +```js +// ES5 Function Constructor +function Person(name, age) { + this.name = name; + this.age = age; +} + +Person.prototype.greet = function () { + console.log( + 'Hello, my name is ' + this.name + ' and I am ' + this.age + ' years old.', + ); +}; + +// Creating an instance +var person1 = new Person('John', 30); +person1.greet(); // Hello, my name is John and I am 30 years old. +``` + +### ES6 Class + +ES6 introduced the class syntax, which simplifies the definition of classes and supports more features such as static methods and subclassing. Here’s the same example using ES6: + +```js +// ES6 Class +class Person { + constructor(name, age) { + this.name = name; + this.age = age; + } + + greet() { + console.log( + `Hello, my name is ${this.name} and I am ${this.age} years old.`, + ); + } +} + +// Creating an instance +const person1 = new Person('John', 30); +person1.greet(); // Hello, my name is John and I am 30 years old. +``` + +### Key Differences + +1. **Syntax and Readability**: + + - **ES5**: Uses function constructors and prototypes, which can be less intuitive and harder to read. + - **ES6**: Uses the `class` keyword, making the code more concise and easier to understand. + +2. **Static Methods**: + + - **ES5**: Static methods are added directly to the constructor function. + - **ES6**: Static methods are defined within the class using the `static` keyword. + + ```js + // ES5 + function Person(name, age) { + this.name = name; + this.age = age; + } + + Person.sayHi = function () { + console.log('Hi!'); + }; + + Person.sayHi(); // Hi! + + // ES6 + class Person { + static sayHi() { + console.log('Hi!'); + } + } + Person.sayHi(); // Hi! + ``` + +3. **Inheritance** + + - **ES5**: Inheritance is achieved using `Object.create()` and manually setting the prototype chain. + - **ES6**: Inheritance is much simpler and more intuitive with the extends keyword. + + ```js + // ES5 Inheritance + + // ES5 Function Constructor + function Person(name, age) { + this.name = name; + this.age = age; + } + + Person.prototype.greet = function () { + console.log( + 'Hello, my name is ' + + this.name + + ' and I am ' + + this.age + + ' years old.', + ); + }; + + function Student(name, age, grade) { + Person.call(this, name, age); + this.grade = grade; + } + + Student.prototype = Object.create(Person.prototype); + Student.prototype.constructor = Student; + + Student.prototype.study = function () { + console.log(this.name + ' is studying.'); + }; + + var student1 = new Student('Alice', 20, 'A'); + student1.greet(); // Hello, my name is Alice and I am 20 years old. + student1.study(); // Alice is studying. + + // ES6 Inheritance + + // ES6 Class + class Person { + constructor(name, age) { + this.name = name; + this.age = age; + } + + greet() { + console.log( + `Hello, my name is ${this.name} and I am ${this.age} years old.`, + ); + } + } + + class Student extends Person { + constructor(name, age, grade) { + super(name, age); + this.grade = grade; + } + + study() { + console.log(`${this.name} is studying.`); + } + } + + const student1 = new Student('Alice', 20, 'A'); + student1.greet(); // Hello, my name is Alice and I am 20 years old. + student1.study(); // Alice is studying. + ``` + +4. Super Calls: + + - **ES5**: Manually call the parent constructor function. + - **ES6**: Use the `super` keyword to call the parent class's constructor and methods. + +### Conclusion + +While both ES5 and ES6 approaches can achieve the same functionality, ES6 classes provide a clearer and more concise way to define and work with object-oriented constructs in JavaScript. This makes the code easier to write, read, and maintain. If you are working with modern JavaScript, it is generally recommended to use ES6 classes over ES5 function constructors + +## Resources + +- [Classes - MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes) +- [Inheritance- MDN ](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes#inheritance) +- [The Secret Life Of Objects](https://eloquentjavascript.net/06_object.html) +- [ES6 vs ES5](https://www.educative.io/courses/learn-object-oriented-programming-in-javascript/es6-vs-es5) diff --git a/packages/quiz/questions/what-is-a-closure-and-how-why-would-you-use-one/en-US.mdx b/packages/quiz/questions/what-is-a-closure-and-how-why-would-you-use-one/en-US.mdx index 8e4c52621..e1ae09670 100644 --- a/packages/quiz/questions/what-is-a-closure-and-how-why-would-you-use-one/en-US.mdx +++ b/packages/quiz/questions/what-is-a-closure-and-how-why-would-you-use-one/en-US.mdx @@ -2,6 +2,40 @@ title: What is a closure, and how/why would you use one? --- +## TL;DR + +In the book ["You Don't Know JS"](https://github.com/getify/You-Dont-Know-JS/tree/2nd-ed/scope-closures) (YDKJS) by Kyle Simpson, a closure is defined as follows: + +> Closure is when a function is able to remember and access its lexical scope even when that function is executing outside its lexical scope + +In simple terms, functions have access to variables that were in their scope at the time of their creation. This is what we call the function's `lexical scope`. A closure is a function that retains access to these variables even after the outer function has finished executing. This is like the function has a `memory` of its original environment. + +```js +function outerFunction() { + const outerVar = 'I am from the outer function'; + + function innerFunction() { + console.log(outerVar); // innerFunction can still access outerVar + } + + return innerFunction; +} + +const closure = outerFunction(); // closure now holds a reference to innerFunction + +closure(); // "I am from the outer function" +// Even though outerFunction has completed execution closure still have access to variables defined inside outer function +``` + +### Key points: + +- Closure occurs when an inner function has access to variables in its outer (lexical) scope, even when the outer function has finished executing. +- Closure allows a function to `remember` the environment in which it was created, even if that environment is no longer present. + +- Closures are used extensively in JavaScript, such as in callbacks, event handlers, and asynchronous functions. + +--- + ## Understanding JavaScript closures In JavaScript, a closure is a function that captures the lexical scope in which it was declared, allowing it to access and manipulate variables from an outer scope even after that scope has been closed. @@ -30,9 +64,54 @@ console.log(counter()); // Outputs: 1 console.log(counter()); // Outputs: 2 ``` +### Closures in React + +Closures are everywhere. Below code shows a simple example of increasing a counter on a button click. In this code, `handleClick` forms a closure. It has access to it's outer scope variable `count` and `setCount` + +```jsx +import React, { useState } from 'react'; + +function Counter() { + // Define a state variable using the useState hook + const [count, setCount] = useState(0); + + // This handleClick function is a closure + function handleClick() { + // It can access the 'count' state variable + setCount(count + 1); + } + + return ( +
Count: {count}
+ +