Может ли свойство объекта JavaScript ссылаться на другое свойство одного и того же объекта?
Недавно я попытался создать такой объект:
var carousel = {
$slider: $('#carousel1 .slider'),
panes: carousel.$slider.children().length
};
Мои намерения заключались в улучшении производительности селектора jQuery путем кэширования результатов $('#carousel1 .slider')
в свойстве объекта и для обеспечения краткости кода и относительно СУХОЙ.
Однако это не сработало. Когда код выполнялся, он генерировал исключение при попытке проанализировать значение panes
, жалуясь, что carousel
был undefined.
Это имеет смысл, так как я предполагаю, что carousel
не объявляется полностью до тех пор, пока оператор присваивания не будет полностью выполнен. Однако я бы не хотел прибегать к этому:
var carousel = {};
carousel.$slider = $('#carousel1 .slider');
carousel.panes = carousel.$slider.children().length;
Это не так уж и плохо, но объект carousel
будет иметь еще несколько свойств, которые полагаются на значения других свойств, чтобы они могли быстро стать подробными.
Я попытался использовать this
, но безрезультатно. Я, возможно, не использовал его правильно, или, возможно, это не действительный подход.
Есть ли способ для свойств объекта ссылаться на другие свойства одного и того же объекта, пока этот объект все еще объявляется?
На основании ответов Matthew Flaschen и casablanca (спасибо, ребята!), я думаю, что это версии моего фактического кода, которые я бы получил, основываясь на каждом подходе:
// 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');
})();
и
// 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;
Предполагая, что они оба правильны (я их не тестировал), это непростой вызов. Я думаю, что я немного предпочитаю подход Мэтью Флашена, поскольку код содержится в структуре, более близкой к объявлению объекта. Там также создается только одна переменная. Однако там много this
, которое кажется повторяющимся - хотя это может быть только цена, которую нужно заплатить.
Ответы
Ответ 1
Не с объектными литералами (this
имеет такое же значение при построении литерала, что и раньше). Но вы можете сделать
var carousel = new (function()
{
this.$slider = $('#carousel1 .slider');
this.panes = this.$slider.children().length;
})();
В этом случае используется объект, созданный из конструктора анонимной функции.
Обратите внимание, что $slider
и panes
являются общедоступными, поэтому их можно получить как carousel.$slider
и т.д.
Ответ 2
К сожалению, нет. Синтаксис {}
инициирует создание нового объекта, но до создания объекта он не присваивается переменной carousel
. Кроме того, значение this
может меняться только в результате вызова функции. Если ваши "несколько свойств" будут зависеть только от slider
, тогда вы можете обойти что-то вроде этого:
var slider = $('.slider');
var carousel = {
panes: slider.children.length(),
something: slider.something_else,
// ...
};
carousel.slider = slider;