Bonjour,

Je fais quelques composants avec VueJS pour mon application frontend. Seulement je me suis aperçu que j'utilisais des objets literraux à plusieurs endroit dans le code qui se répétaient. Je me suis donc dit qu'il fallait refactorisait le code avec des classes. Mais j'ai lu beaucoup d'articles qui déconseillent d'utiliser les classes au profits des fonctions factory (une fonction qui retourne un objet si j'ai bien compris :P ). Seulement je ne suis pas sûr de suivre pourquoi exactement. Ils parlent (les articles sont quasiement toujours en anglais) essentiellement du mot clé new et this et des conséquences que ça peut avoir etc. Mais admettons que je suis du genre à nen pas oublier le mot clé new ? Dans ce cas il reste le problème du mot clé this qui peut porter à confusion. Mais si on l'utilise correctement dans la classe, quels sont les problèmes que l'on risque de rencontrés ?

Par ailleurs, en utilisant les fonctions Factory, on retourne un object qui est une instance de Object. Mais si je veux qu'il soit une instance de Period par exemple afin de pouvoir faire quelques tests vie l'opérateur instanceof dans mon code ? Il y a bien une façon de faire ça non ?

Merci à tout ceux qui pourraient éclairer ma lanterne car je n'y comprends plus grand chose.

2 réponses


une factory, comme sont nom l'indique, une usine. Elle vas te permettre d'instancier tes objets pour toi sans avoir recour au mot clé new partout dans ton code. Je ne comprend pas ton intérogation à propos du thisparcontre. Pourrait tu etre plus clair?

Voici par exemple un des articles que j'ai lu. Dans les bienfaits des fonctions constructrices, l'auteur mentionne que this pointe vers le nouvel objet. Pour les fonctions factory (usine :) ) il parle de fonctionnement standart du mot clé this.

En fait, je me rends compte en relisant l'article que je ne comprends pas vraiment pourquoi on doit éviter les classes. Par exemple, il mentionne que factory ne permet par l'utilisation du mot clé instanceof (enfin il ne permet pas de l'utiliser pour un prototype perso) et que c'est une bonne chose.

Seulement, dans mon code, je n'ai pas de notion d'héritage et je ne cherche pas à changer le prototype de l'objet ou quoi que ce soit dans le style. Donc normalement, instanceof devrait fonctionner correctement... Quand au mot clé new, il ne m'a jamais vraiment posé de problèmes sur des langages plus fortement typés (Java par exemple). Comme l'orienté objet en JavaScript fonctionne différement, j'entends bien qu'il peut y avoir des conséquences néfastes à l'utilisation de new. Seulement je ne les ai pas compris...

Par exemple, voici deux façons que j'ai de créer un objet qui me sert de collection personnalisée pour gérer un tableau de périodes :

Factory function

import moment from 'moment'

function PeriodsCollection (periods) {
  return {
    periods,

    /**
     * Returns if a day is in one of all the periods
     * @param {moment} day The day it's looking for
     * @returns {Boolean}
     */
    contains (day) {
      if (day instanceof moment) {
        let result = false
        this.periods.forEach(period => {
          if (period.contains(day)) {
            result = true
          }
        })
        return result
      } else {
        throw new TypeError('Invalid Parameters. Moment object expected. See doc for more informations')
      }
    },

    /**
     * Adds a period to the collection
     * @param {Object} period The period to be added to the collection
     */
    add (period) {
      if (period instanceof Object) {
        this.periods.push(period)
      } else {
        throw new TypeError('Invalid parameter. Period object expected. Read doc for more informations.')
      }
    },

    /**
     * Removes a specific period from the collection
     * @param {Period} period The period to be removed from the collection
     */
    remove (period) {
      if (period instanceof Object) {
        let self = this
        this.periods.forEach(elt => {
          if (period === elt) {
            self.periods.splice(self.periods.indexOf(period), 1)
          }
        })
      } else {
        throw new TypeError('Invalid parameter. Period object expected. Read doc for more informations.')
      }
    }
  }
}

export default PeriodsCollection

Sous forme de classe

import moment from 'moment'
import Period from './Period'

export default class PeriodsCollection {
  /**
   * Represents a stack of periods
   *
   * @constructor
   * @param {Period[]} periods - An array of the periods
   */
  constructor (periods) {
    if (periods.length > 0) {
      periods.forEach(period => {
        if (!(period instanceof Period)) {
          throw new TypeError('Invalid parameter. Period moment expected. Read the doc for more informations')
        }
      })
    } else {
      periods = []
    }

    this.periods = periods
  }

  /**
   * Returns if a day is in one of all the periods
   * @param {moment} day The day it's looking for
   * @returns {Boolean}
   */
  contains (day) {
    if (day instanceof moment) {
      let result = false
      this.periods.forEach(period => {
        if (period.contains(day)) {
          result = true
        }
      })
      return result
    } else {
      throw new TypeError('Invalid Parameters. Moment object expected. See doc for more informations')
    }
  }

  /**
   * Adds a period to the collection
   * @param {Period} period The period to be added to the collection
   */
  add (period) {
    if (period instanceof Period) {
      this.periods.push(period)
    } else {
      throw new TypeError('Invalid parameter. Period object expected. Read doc for more informations.')
    }
  }

  /**
   * Removes a specific period from the collection
   * @param {Period} period The period to be removed from the collection
   */
  remove (period) {
    if (period instanceof Period) {
      let self = this
      this.periods.forEach(elt => {
        if (period === elt) {
          self.periods.splice(self.periods.indexOf(period), 1)
        }
      })
    } else {
      throw new TypeError('Invalid parameter. Period object expected. Read doc for more informations.')
    }
  }
}