web-dev-qa-db-fra.com

Une propriété d'objet JavaScript peut-elle faire référence à une autre propriété du même objet?

J'ai récemment essayé de créer un objet comme celui-ci:

var carousel = {
      $slider: $('#carousel1 .slider'),
      panes: carousel.$slider.children().length
    };

Mes intentions étaient d'améliorer les performances du sélecteur de jQuery en mettant en cache les résultats de $('#carousel1 .slider') dans une propriété d'objet, et de garder le code concis et relativement SEC.

Cependant, cela n'a pas fonctionné. Lorsque le code a été exécuté, il a levé une exception en essayant d'analyser la valeur de panes, se plaignant que carousel n'était pas défini.

Cela a du sens, car je suppose que carousel n'est pas entièrement déclaré tant que l'instruction d'affectation n'a pas été entièrement exécutée. Cependant, je voudrais éviter de recourir à ceci:

var carousel = {};
carousel.$slider = $('#carousel1 .slider');
carousel.panes = carousel.$slider.children().length;

Ce n'est pas trop pire, mais l'objet carousel aura plusieurs autres propriétés qui reposent sur les valeurs d'autres propriétés, ce qui pourrait rapidement devenir verbeux.

J'ai essayé d'utiliser this, mais en vain. Je ne l'ai peut-être pas utilisé correctement, ou ce n'est peut-être pas une approche valable de toute façon.

Existe-t-il un moyen pour les propriétés d'un objet de se référer à d'autres propriétés du même objet, alors que cet objet est encore en cours de déclaration?


Sur la base des réponses de Matthew Flaschen et de casablanca (merci, les gars!), Je pense que ce sont les versions de mon code réel avec lesquelles je me retrouverais, en fonction de chaque approche:

// Matthew Flaschen

var carousel = new (function() {
  this.$carousel = $('.carousel');
  this.$carousel_window = this.$carousel.find('.window');
  this.$carousel_slider = this.$carousel.find('.slider');
  this.$first_pane = this.$carousel.find('.slider').children(':first-child');
  this.panes = this.$carousel_slider.children().length;
  this.pane_gap = this.$first_pane.css('margin-right');
})();

et

// casablanca

var $carousel = $('.carousel'),
    $carousel_slider = $carousel.find('.slider'),
    $first_pane: $carousel.find('.slider').children(':first-child');

var properties = {
  $carousel_window: $carousel.find('.window'),
  panes: $carousel_slider.children().length,
  pane_gap: $first_pane.css('margin-right')
};

properties.$carousel = $carousel;
properties.$carousel_slider = $carousel_slider;
properties.$first_pane = $first_pane;

En supposant que ceux-ci sont corrects (je ne les ai pas testés), c'est une sorte d'appel difficile. Je pense que je préfère légèrement l'approche de Matthew Flaschen, car le code est contenu dans une structure qui ressemble plus à une déclaration d'objet. Il n'y a également finalement qu'une seule variable créée. Cependant, il y a beaucoup de this là-dedans, ce qui semble répétitif - bien que ce soit peut-être juste le prix à payer.

62
Bungle

Pas avec les littéraux d'objet (this a la même valeur lors de la construction du littéral qu'auparavant). Mais tu peux faire

var carousel = new (function()
{
      this.$slider =  $('#carousel1 .slider');
      this.panes = this.$slider.children().length;
})();

Cela utilise un objet créé à partir d'un constructeur de fonction anonyme.

Notez que $slider et panes sont publics, donc accessibles en tant que carousel.$slider, etc.

50
Matthew Flaschen

Malheureusement non. La syntaxe {} Lance la création d'un nouvel objet, mais tant que l'objet n'est pas créé, il n'est pas affecté à la variable carousel. De plus, la valeur this ne peut changer qu'à la suite d'un appel de fonction. Si vos "plusieurs autres propriétés" ne dépendent que de slider, vous pouvez vous déplacer avec quelque chose comme ceci:

var slider = $('.slider');
var carousel = {
  panes: slider.children.length(),
  something: slider.something_else,
  // ...
};
carousel.slider = slider;
19
casablanca