52

Recientemente he tratado de crear un objeto como éste:¿Puede una propiedad de objeto JavaScript referirse a otra propiedad del mismo objeto?

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

Mis intenciones eran para mejorar el rendimiento del selector de jQuery almacenamiento en caché de los resultados de $('#carousel1 .slider') en una propiedad de objeto, y para mantener el código conciso y relativamente seco.

Sin embargo, esto no funcionó. Cuando se ejecutó el código, arrojó una excepción al intentar analizar el valor de panes, quejándose de que carousel no estaba definido.

Esto tiene sentido, ya que supongo que carousel no está completamente declarado hasta que la instrucción de asignación se haya ejecutado por completo. Sin embargo, me gustaría evitar tener que recurrir a esto:

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

Eso no es mucho peor, pero el objeto carousel tendrá varios más propiedades que dependen de los valores de otras propiedades, por lo que podría convertirse rápidamente en verbosa.

Intenté usar this, pero fue en vano. Es posible que no lo haya estado usando correctamente, o que no sea un enfoque válido de todos modos.

¿Hay alguna manera de que las propiedades de un objeto hagan referencia a otras propiedades del mismo objeto, mientras ese objeto todavía se está declarando? (¡Gracias, chicos)


Basado en Mateo Flaschen y respuestas de Casablanca, creo que estas son las versiones de mi código real que iba a terminar con la función de cada enfoque:

// 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'); 
})(); 

y

// 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; 

Suponiendo que esos son ambos correctos (no los he probado), que es un poco una decisión difícil. Creo que prefiero un poco el enfoque de Matthew Flaschen, ya que el código está contenido en una estructura que se asemeja más a una declaración de objeto. También, en última instancia, solo se creó una sola variable. Sin embargo, hay un montón de this allí, lo que parece repetitivo, aunque ese puede ser el precio a pagar.

+1

OP: Duplicar no está determinado necesariamente por orden cronológico. Tratamos de apuntar todo a las preguntas con respuestas más detalladas y extensas, con el objetivo de señalar una pregunta * canónica *. Sin embargo, este no es un objetivo fácil. Marcar una pregunta como esta como duplicado no es una marca en contra. Su pregunta aparecerá en los motores de búsqueda con diferentes términos, y si estas respuestas no resuelven la solución, la otra pregunta (más extensa) podría. – CodeMouse92

+0

En este caso, escribí lo que ahora se considera una pregunta canónica, y muchas preguntas antiguas, de enfoque más restringido, se marcan como duplicados, para canalizar a los visitantes del sitio hacia las respuestas más completas. Siéntete orgulloso: tu pregunta "duplicada" está ayudando. :) – CodeMouse92

+0

Gracias por aclarar @ JasonMc92, eso tiene sentido. Eliminaré mi actualización. – Bungle

Respuesta

42

No con literales de objeto (this tiene el mismo valor durante la construcción del literal que antes). Pero puede hacerlo

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

Esto utiliza un objeto creado a partir de un constructor de función anónima.

Tenga en cuenta que $slider y panes son públicos, por lo que es posible acceder a carousel.$slider, etc.

+0

Esta es esencialmente una versión más detallada del segundo ejemplo del PO. – casablanca

+1

@casablanca, no realmente. Él preguntó: "¿Hay alguna manera de que las propiedades de un objeto se refieran a otras propiedades del mismo objeto, mientras ese objeto todavía se está declarando?", Y eso es exactamente lo que es. Con mi ejemplo, 'carrusel' puede usar propiedades previamente definidas, pero no es accesible desde el exterior hasta que esté completamente construido. Con su código, ese no era el caso. Y * usa * 'this' (que OP dijo que quería), en lugar de tener que repetir' carrusel'. Dijo que planeaba agregar más propiedades, lo que también podría acortar este enfoque. –

+1

Supongo que tienes razón al respecto. – casablanca

17

Por desgracia, no. La sintaxis {} inicia la creación de un nuevo objeto, pero hasta que se crea el objeto, no se asigna a la variable carousel. Además, el valor this solo puede cambiar como resultado de una llamada a función.Si sus "varios más propiedades" todos van a depender sólo de slider, entonces se podría moverse con algo como esto:

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

Gracias, casablanca! Me gusta su enfoque para los casos en que la mayoría de las propiedades de los objetos se basan en una o dos variables más. Para mi caso de uso, desafortunadamente, ese no es el caso, así que creo que el enfoque de Matthew Flaschen es un poco más elegante. Gracias de nuevo. – Bungle

Cuestiones relacionadas