POO en JS

PHPz
PHPzoriginal
2024-08-29 13:39:211129parcourir

OOP in JS

Le paradigme fait référence au style de code, à la manière dont il est organisé. Les paradigmes de programmation courants sont : POO, Fonctionnel, etc. Pour être un développeur, vous devez bien connaître la POO.

POO

  • paradigme de programmation d'entreprise le plus populaire.
  • basé sur des objets
  • développé dans le but d'organiser le code
  • rend le code plus flexible et maintenable.
  • Avant la POO, le code était dispersé sur plusieurs fns dans une portée globale sans aucune structure. Ce style s'appelait code spaghetti et est très difficile à maintenir, oubliez l'ajout de nouvelles fonctionnalités.
  • utilisé pour créer des objets via du code.
  • permet également l'interaction des objets les uns avec les autres.

API

  • méthodes auxquelles le code extérieur à l'objet peut accéder et utiliser pour communiquer avec d'autres objets.

Classe

  • plan abstrait pour créer des objets.
  • instancié à partir de classes, c'est-à-dire créé à l'aide du plan de classe.
  • plusieurs objets sont créés à partir d'une classe en utilisant la syntaxe 'new Class()'

Conception de la classe :

  • Réalisé en utilisant 4 principes de la POO à savoir l'abstraction, l'encapsulation, l'héritage, le polymorphisme
  • Abstraction : masquage des détails inutiles qui n'ont pas d'importance pour l'utilisateur final.
  • Encapsulation : conserver certaines propriétés-méthodes comme privées, ce qui les rend accessibles uniquement depuis l'intérieur de la classe, et les rendre inaccessibles depuis l'extérieur de la classe. Exposez quelques méthodes en tant qu'API d'interface publique pour interagir avec le monde extérieur. Par conséquent, cela empêche le code externe de manipuler l'état interne [les données de l'objet] car cela peut être une grande source de bugs. L'interface publique est le code qui n'est pas privé. Rendre les méthodes privées nous permet de modifier plus facilement l'implémentation du code sans rompre les dépendances externes. Résumé : Encapsulez joliment l'état et les méthodes et ne rendez publiques que les méthodes essentielles.
  • Héritage : le code en double est difficile à conserver. Par conséquent, ce concept prend en charge la réutilisabilité du code en héritant du code déjà écrit. La classe enfant étend la classe parent en héritant de toutes les propriétés et méthodes de la classe parent. De plus, la classe enfant implémente sa propre fonctionnalité de données ainsi que les fonctionnalités héritées.
  • Polymorphisme : une classe enfant peut écraser une méthode héritée de la classe parent.

Les objets sont :

  • utilisé pour modéliser des fonctionnalités du monde réel ou abstraites.
  • peut contenir des données (propriétés) et du code (méthodes). aidez-nous à regrouper les données et le code en un seul bloc
  • morceaux/blocs de code autonomes.
  • Les éléments constitutifs de l'application interagissent les uns avec les autres.
  • Les objets d'interaction n/b se produisent via l'API de l'interface publique.
  • Tous les objets créés à partir d'une classe sont appelés instances de cette classe.
  • Tous les objets peuvent contenir des données différentes, mais ils partagent tous des fonctionnalités communes

Héritage classique :

  • Supporté par Java, C++, Python, etc.
  • une classe hérite d'une autre classe
  • les méthodes ou le comportement sont copiés de la classe vers toutes les instances.

Délégation ou héritage prototypique en JS :

  • Prend en charge tous les principes de la POO comme dans les langages classiques.
  • une instance héritant d'une classe.
  • Prototype contient toutes les méthodes accessibles à tous les objets liés à ce prototype. prototype : contient des méthodes object : peut accéder aux méthodes du prototype, connectées à l'objet prototype à l'aide du lien proto.
  • les objets héritent des propriétés et de la méthode définies sur l'objet prototype.
  • les objets délèguent leur comportement à l'objet prototype.
  • Une instance de tableau définie par l'utilisateur accède au .map() sur Array.prototype.map(), c'est-à-dire map() défini sur l'objet prototype via le lien proto. Par conséquent, .map() n’est pas défini sur notre instance, mais plutôt sur le prototype.
## 3 Ways to implement Prototypal Inheritance via:
1. Constructor Fn:
- To create objects via function.
- Only difference from normal fn is that they are called with 'new' operator.
- Convention: always start with a capital letter to denote constructor fn. Even builtins like Array, Map also follow this convention.
- An arrow function doesn't work as Fn constructor as an arrow fn doesn
t have its own 'this' keyword which we need with constructor functions.
- Produces an object. 
- Ex. this is how built-in objects like Array, Maps, Sets are implemented

2. ES6 Classes:
- Modern way, as compared to above method.
- Syntactic sugar, although under the hood work the same as above syntax.
- ES6 classes doesn't work like classical OOP classes.

3. Object.create()
- Way to link an object to its prototype
- Used rarely due to additional repetitive work.

## What does 'new' operator automates behind the scene?
1. Create an empty object {} and set 'this' to point to this object.
2. Create a __proto__ property linking the object to its parent's prototype object.
3. Implicit return is added, i.e automatically return 'this {} object' from the constructor fn.

- JS doesn't have classes like classical OOP, but it does create objects from constructor fn. Constructor fn have been used since inception to simulate class like behavior in JS.
Ex. validate if an object is instance of a constructor fn using "instanceOf" operator.

const Person = function(fName, bYear) {
  // Instance properties as they will be available on all instances created using this constructor fn.
  this.fName = fName;
  this.bYear = bYear;

  // BAD PRACTICE: NEVER CREATE A METHOD INSIDE A CONSTRUCTOR FN.
  this.calcAge = function(){
console.log(2024 - this.bYear);
}
};

const mike = new Person('Mike', 1950);
const mona = new Person('Mona', 1960);
const baba = "dog";

mike; // Person { fName: 'Mike', bYear: 1950 }
mona; // Person { fName: 'Mona', bYear: 1960 }

mike instanceof Person; // true
baba instanceof Person; // true


If there are 1000+ objects, each will carry its own copy of fn defn.
Its a bad practice to create a fn inside a contructor fn as it would impact performance of our code.

Objet prototype :

  • Chaque fonction, y compris le constructeur fn dans JS, a une propriété appelée objet prototype.
  • Chaque objet créé à partir de ce constructeur fn aura accès à l'objet prototype du constructeur fn. Ex. Personne.prototype
  • Ajoutez fn à cet objet prototype via : Personne.prototype.calcAge = fonction (bAnnée){ console.log(2024 - bAnnée); };

mike.calcAge(1970); // 54
mona.calcAge(1940); // 84

  • L'objet Mike ne contiendra pas le .calcAge() mais il y accédera en utilisant le lien proto défini sur l'objet Person.prototype.
  • 'this' est toujours défini sur l'objet appelant la fonction.

mike.proto; // { calcAge : [Fonction (anonyme)] }
mona.proto; // { calcAge : [Fonction (anonyme)] }

mike.proto === Person.prototype; // vrai

  • Person.prototype here serves as prototype for all the objects, not just this single object created using Person constructor fn.

Person.prototype.isPrototypeOf(mike); // true
Person.prototype.isPrototypeOf(Person); // false

  • prototype should have been better named as prototypeOfLinkedObjects generated using the Constructor fn.
  • Not just methods, we can create properties also on prototype object. Ex. Person.prototype.creatureType = "Human"; mike.creatureType; // Human mona.creatureType; // Human

Different properties for an object:

  • Own property and properties on constructor fn accessbile via proto link of objects.
  • To check own property for objects, use:
    mike.hasOwnProperty('fName'); // true
    mona.hasOwnProperty('creatureType'); // false

  • Two way linkage:
    Person() - constructor fn
    Person.prototype - Prototype

Person() constructor fn links to Person.prototype via .prototype
Person.prototype prototype links back to Person() constructor fn via .constructor to Person() itself.

proto : always points to Object's prototype for all objects in JS.
newly created object is automatically returned, unless we explicitly return something else and stored in the LHS variable declared.

Prototype Chain:

  • Similar to scope chain. Look for variable in the scope level
  • Prototype chain has to lookup for finding properties or methods.
  • All objects in JS has a proto link Person Person.proto Person.proto.proto; // [Object: null prototype] {}

Top Level Object in JS:
Object() - constructor fn
Object.prototype - Prototype
Object.prototype.proto // null

Object.prototype methods:

  • constructor: f Object()
  • hasOwnProperty
  • isPrototypeOf
  • propertyIsEnumerable
  • toLocaleString
  • toString
  • valueOf
  • defineGetter etc

// Takes to constructor fn prototype
mike.proto === Person.prototype; // true
// Takes to parent of constructor fn's prototype i.e Object fn
mike.proto.proto; // [Object: null prototype] {}
// Takes to parent of Object fn i.e end of prototype chain
mike.proto.proto.proto; // null

  • All fns in JS are objects, hence they also have a prototype
  • console.dir(x => x+1);
  • Fns are objects, and objects have prototypes. So a fn prototype has methods which can be called.
  • const arr = [2,4,21]; // is same as using 'new Array' syntax
    arr.proto; // shows fns on array's prototype

  • Each array doesn't have all of these methods, its able to use it via proto link.

  • arr.proto === Array.prototype; // true

const arr = [2,4,21];
arr.proto; // Array prototype
arr.proto.proto; // Object prototype
arr.proto.proto.proto; // null

## If we add a fn to Array.prototype, then all newly created arrays will inherit that method. However extending the prototype of a built-in object is not a good idea. Incase new version of JS adds a method with the same name, will break your code. Or in case multiple Devs create similar fnality with different names will add an unnecessary overhead.
Ex. Add a method named unique to get unique values
const arr = [4,2,4,1,2,7,4,7,3];
Array.prototype.uniq = function(){
return [...new Set(this)];
}
arr.uniq(); // [ 4, 2, 1, 7, 3 ]
  • All DOM elements behind the scene are objects.
  • console.dir(h1) // will show you it in object form
  • Prototype chain: h1 -> HTMLHeadingElement -> HTMLElement -> Element -> Node -> EventTarget -> Object

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn