"Si un ouvrier veut bien faire son travail, il doit d'abord affûter ses outils." - Confucius, "Les Entretiens de Confucius. Lu Linggong"
Page de garde > La programmation > POO en JS -

POO en JS -

Publié le 2024-11-04
Parcourir:547

OOP in JS -

  • Les classes JS sont comme du sucre syntaxique, pas les mêmes que les classes d'autres langages fortement typés.
  • Ajoute uniquement un emballage syntaxique pour le rendre familier aux développeurs provenant d'autres langages.
  • Les classes
  • sont un type spécial de fonctions en arrière-plan et peuvent donc être écrites sous forme d'expression de classe ainsi que de déclaration de classe.
## class expression:
const Person = class {
}

## class declaration:
class Person {
  constructor(fName, bYear){
   this.fName = fName;
   this.bYear = bYear;
  }
  calcAge(){
   console.log(2024 - this.bYear);
  }
}

- constructor is a method of this class. Pass values for properties to have in objects created using this fn.
- then set the properties of the object using this.xxx = xxx;
- On using 'new' operator, this constructor will be called automatically and return a new object which will be stored in LHS variable as shown below.
Ex. const ronald = new Person('ronald',1975); // Person { fName: 'ronald', bYear: 1975 }
- Methods are written outside the constructor fn and will be added to the prototype property of the object which can be verified using devConsole.
Ex. ronald.calcAge(); // 49

ronald.__proto__ === Person.prototype; // true

- No commas need to be added while adding multiple methods below the constructor fn inside the class.

## Hence, the above syntax works same as constructor fn syntax but with a familiar syntax of strongly typed class based languages.

## Adding a fn explicitly to the prototype:
Person.prototype.greet = function(){
console.log(`Hey ${this.fName}`);
}
ronald.greet(); // 'Hey ronald'

Points d'imposition :

  • Les déclarations Fn sont levées tandis que les déclarations Class ne sont PAS levées.
  • Également citoyen de première classe, tout comme Fns, c'est-à-dire qu'il peut être transmis et renvoyé depuis FNS.
  • Le corps de classe est toujours exécuté en mode strict, que l'on active ou non le mode strict.
  • Les classes donnent au code un aspect plus propre, avec un bruit de caractère réduit, à condition que vous sachiez comment il est implémenté sous le capot. ** Pour devenir un expert en JS, vous devez comprendre les détails complexes d'implémentation du langage, comme avec les cours.

Propriétés de l'accesseur : getters et setters, c'est-à-dire des fns qui obtiennent et définissent la valeur. Mais de l'extérieur, ils ressemblent toujours à des propriétés ordinaires.

Les propriétés normales sont appelées propriétés de données.

  • Les getters et settters sont communs à tous les objets dans JS, c'est-à-dire que chaque objet peut avoir des propriétés getter et setter. Ces getter-setter sont appelés propriétés d'accesseur, tandis que les propriétés normales sont appelées propriétés de données.

- Getter & setter sont des fns qui obtiennent et définissent une valeur, qui, de l'extérieur, ressemblent à des propriétés normales.

const account = {
  owner: 'jonas',
  movements: [200,300,100,500],
  get latest(){
    // will return an array with last value. Hence, use pop to get the value.
    return this.movements.slice(-1).pop();
  },
  set latest(mov){
    this.movements.push(mov);
  }
}

account.latest; // 500
account.latest = 50; 
account.latest; // 50

Just like above, classes also support the getter-setter methods but acccessed like using a property syntax.

These are very useful for data validation.

Méthodes statiques

Ex. Array.from() = Convertit une structure de type tableau en tableau.
Array.from(document.querySelector('h1'));
Array.from(document.querySelectorAll('h1'));

Ex. .from est attaché au constructeur Array, pas à la propriété prototype du constructeur. Par conséquent, tous les tableaux n'héritent pas de ce fn.
[1,2,3].from(); // .from n'est pas une fonction

Ex. Number.parseFloat(12) est une méthode statique sur le constructeur Number, non disponible sur les variables numériques.

Création d'une méthode statique.

// Static methods are not inherited. They are not added to prototype.
className.fnName = function(){
  console.log(this); // Entire constructor() which is calling the method
  console.log("JS is awesome")
};
className.fnName();

// Rule =  whatever object is calling the method, 'this' points to that object inside the fn. Hence its simply the entire constructor() above.

//Inside class, we need to use static keyword for adding a static method.
static fnName = function(){
  console.log(this); // can point to the entire class defn
  console.log("JS is awesome")
};

// Static methods and instance methods will be different from each other.
// instance methods will be prototype, hence all instances can have access to them

Objet.create() :

Utilisé manuellement pour définir le prototype de notre objet sur n'importe quel objet de notre choix.
Sera utilisé pour implémenter les classes d'héritage n/b.
Héritage prototypique implémenté à l'aide de ce fn.
Object.create renvoie un objet vide.
Fonctionne d'une manière différente selon laquelle les fns et les classes du constructeur fonctionnent.
Il existe toujours une idée d'héritage prototypique, même sans l'implication des opérateurs « prototype », « constructeur() », « nouveau ».

const PersonProto = {
  // This method will be looked up using __proto__ link
  calcAge(){
    console.log(2024 - this.bYear);
  }
};

// baba will be created, with its prototype set to PersonProto object.
const baba = Object.create(PersonProto);
baba;

baba.name = 'Roger';
baba.bYear = '2000';
baba.calcAge();

Constructeur Fn --(.prototype)--> Personne.prototype
Instance d'objet --(proto)--> Person.prototype

Fonctionne exactement comme cela fonctionnait pour les constructeurs fn ou dans les classes
Pas besoin de propriété constructor() ou .prototype pour atteindre cet objectif.

const PersonProto = {
  // This method will be looked up using __proto__ link
  calcAge(){
    console.log(2024 - this.bYear);
  },
  // Noting special with init name, its a normal fn here.
  // This has nothing to with ES6 constructor()
  // Manual way of initialzing an object.
  init(fName, bYear){
    this.fName = fName;
    this.bYear = bYear;
  }
};

// baba will be created, with its prototype set to PersonProto object.
const baba = Object.create(PersonProto);
baba;

baba.name = 'Roger';
baba.bYear = '2000';
baba.calcAge();

baba.__proto__;    // { calcAge: [Function: calcAge] }
baba.__proto__ === PersonProto; //true


const alice = Object.create(PersonProto);
alice.init("alice", 2000);
alice;   // { fName: 'alice', bYear: 2000 }  

Façons de créer un héritage prototypique :
Constructeur Fn
Cours ES6
Objet.create

Héritage entre classes utilisant constructor() :

Toutes ces techniques permettent à un objet de rechercher des méthodes sur son prototype.
Les vraies classes n'existent pas dans JS.

const Person = function(firstName, bYear){
  this.firstName = firstName;
  this.bYear = bYear;
};

Person.prototype.calcAge = function(){
  console.log(2024 - this.bYear);
};

const Student = function(firstName, bYear, course){
  // This is the duplicate code, any change in Person won't be reflected here.
  this.firstName = firstName;
  this.bYear = bYear;
  this.course = course;
};

Student.prototype.introduce = function(){
  console.log(`My name is ${this.firstName} and I study ${this.course}`);
}

const matt = new Student("Matt", 2000, "CSE");
matt.introduce(); //  'My name is Matt and I study CSE'

Suppression du code redondant de l'exemple ci-dessus :

const Person = function(firstName, bYear){
  this.firstName = firstName;
  this.bYear = bYear;
};

Person.prototype.calcAge = function(){
  console.log(2024 - this.bYear);
};

const Student = function(firstName, bYear, course){
  // Person(firstName, bYear); -> This doesn't work because we are calling it as a regular fn call. 'new' has to be used to call this fn constructor. This fn call is simply a regular fn call, in which 'this' is set 'undefined'. Hence, an error as it cannot set firstName on undefined.
  // We want to set the 'this' inside this fn to be same as inside Person above.
  Person.call(this, firstName, bYear);
  this.course = course;
};

Student.prototype.introduce = function(){
  console.log(`My name is ${this.firstName} and I study ${this.course}`);
}

const matt = new Student("Matt", 2000, "CSE");
matt.introduce(); //  'My name is Matt and I study CSE'

'new' fait automatiquement un lien entre l'instance d'objet et son prototype via proto
L'idée générale de l'héritage est que la classe enfant peut partager le comportement des classes parents en amont de la chaîne de prototypes.
Prototype[Object.prototype] = null ; // Se trouve au sommet de la chaîne de prototypes.

const Person = function(firstName, bYear){
  this.firstName = firstName;
  this.bYear = bYear;
};

Person.prototype.calcAge = function(){
  console.log(2024 - this.bYear);
};

const Student = function(firstName, bYear, course){
  Person.call(this, firstName, bYear);
  this.course = course;
};

// Student.prototype = Person.prototype; => This doesn't work because we won't get the prototype chain, rather we will get 
// Constructor fn[i.e Person()]    --------------> Person.prototype
// Constructor fn[i.e Student()]   --------------> Person.prototype
// Object [Matt] __proto__: Student.prototype ---> Person.prototype

// Student.prototype manually linked for lookup to Person.prototype.
// This has to be done here and not after else Object.create will overwrite any of the existing methods like introduce() on it.
Student.prototype = Object.create(Person.prototype);

Student.prototype.introduce = function(){
  console.log(`My name is ${this.firstName} and I study ${this.course}`);
}

const matt = new Student("Matt", 2000, "CSE");
matt.introduce(); //  'My name is Matt and I study CSE'
matt.calcAge();    // 24

matt.__proto__;                   // Person { introduce: [Function (anonymous)] }
matt.__proto__.__proto__;        // { calcAge: [Function (anonymous)] }
matt.__proto__.__proto__.__proto__;   // [Object: null prototype] {}

Student.prototype.constructor = Student;   // [Function: Student]

matt instanceof Student; // true
matt instanceof Person; // true
matt instanceof Object; // true
Déclaration de sortie Cet article est reproduit sur : https://dev.to/mahf001/oops-in-js-22-5a2n?1 En cas de violation, veuillez contacter [email protected] pour le supprimer.
Dernier tutoriel Plus>

Clause de non-responsabilité: Toutes les ressources fournies proviennent en partie d'Internet. En cas de violation de vos droits d'auteur ou d'autres droits et intérêts, veuillez expliquer les raisons détaillées et fournir une preuve du droit d'auteur ou des droits et intérêts, puis l'envoyer à l'adresse e-mail : [email protected]. Nous nous en occuperons pour vous dans les plus brefs délais.

Copyright© 2022 湘ICP备2022001581号-3