quiz/js: closure and es6 class vs es5 function constructor (#443)

Co-authored-by: Yangshun Tay <tay.yang.shun@gmail.com>
This commit is contained in:
Vikas yadav 2024-06-05 06:03:19 +05:30 committed by GitHub
parent b09b96192f
commit 7fc2166491
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 268 additions and 0 deletions

View File

@ -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. Heres 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. Heres 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)

View File

@ -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 (
<div>
<p>Count: {count}</p>
<button onClick={handleClick}>Increment</button>
</div>
);
}
function App() {
return (
<div>
<h1>Counter App</h1>
<Counter />
</div>
);
}
export default App;
```
### Why use closures?
1. **Data encapsulation**: Closures provide a way to create private variables and functions that can't be accessed from outside the closure. This is useful for hiding implementation details and maintaining state in an encapsulated way.
1. **Functional programming**: Closures are fundamental in functional programming paradigms, where they are used to create functions that can be passed around and invoked later, retaining access to the scope in which they were created, e.g. [partial applications or currying](https://medium.com/javascript-scene/curry-or-partial-application-8150044c78b8#.l4b6l1i3x).
1. **Event handlers and callbacks**: In JavaScript, closures are often used in event handlers and callbacks to maintain state or access variables that were in scope when the handler or callback was defined.
1. **Module patterns**: Closures enable the [module pattern](https://www.patterns.dev/vanilla/module-pattern) in JavaScript, allowing the creation of modules with private and public parts.
## Resources
- [Closures - MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures)
- [Closures - Javascript.info](https://javascript.info/closure)
- [Closure - Eloquent Javascript](https://eloquentjavascript.net/03_functions.html)
- [You Don't Know JS Yet: Scope & Closures](https://github.com/getify/You-Dont-Know-JS/tree/2nd-ed/scope-closures)