JavaScript对象的属性能否引用同一对象的另一个属性?

87

我最近尝试创建一个像这样的对象:

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

我的目的是通过将$('#carousel1 .slider')的结果缓存到一个对象属性中来提高jQuery选择器的性能,并使代码简洁且相对DRY。

然而,这并没有起作用。当代码执行时,在尝试解析panes的值时,它会抛出一个异常,指出carousel未定义。

这很有道理,因为我认为在赋值语句完全执行之前,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;

假设这两种方法都是正确的(我没有测试过),这是一个有点棘手的问题。我认为我稍微更喜欢Matthew Flaschen的方法,因为代码被包含在更像对象声明的结构中。而且最终只创建了一个变量。然而,里面有很多this,看起来有些重复 - 尽管可能只是需要付出的代价。


1
操作:重复并不一定是按时间顺序确定的。我们试图将所有内容指向具有更详细和广泛答案的问题,目标是指向一个规范问题。然而,这并不是一个容易实现的目标。将此类问题标记为重复并不是对其的打击。您的问题将在搜索引擎上以不同的术语出现,如果这些答案不能解决问题,则其他(更广泛)的问题可能会出现。 - CodeMouse92
举例来说,我创作了现在被认为是标准问题的内容,许多较旧、焦点更窄的问题都被标记为重复内容,以引导站点访问者前往最完整的答案。为此感到自豪 - 你的“重复”问题是有帮助的。 :) - CodeMouse92
谢谢您澄清,@JasonMc92,这很有道理。我会删除我的更新。 - Bungle
2个回答

61

不能使用对象字面量(this在创建字面量时的值与之前相同)。但是你可以这样做:

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

这里使用了一个通过匿名函数构造器创建的对象。

需要注意的是$sliderpanes是公开的,所以可以通过carousel.$slider等方式进行访问。


这本质上是 OP 的第二个示例的更冗长版本。 - casablanca
1
@casablanca,不完全是这样。他问道:“是否有一种方法使对象的属性引用同一对象的其他属性,同时该对象仍在声明中?”而这正是这个例子的例子。使用我的示例,carousel可以使用先前定义的属性,但在完全构建之前无法从外部访问。在他的代码中,情况并非如此。它确实使用this(OP说他想要的),而不必重复carousel。他说他计划添加更多属性,这可能会使这种方法更短。 - Matthew Flaschen
1
我想你说得对。 - casablanca
谢谢,马修!实际上我并不完全确定要使用this,只是在这种情况下似乎可能适用。尽管有许多对this的引用,但我想不出比你建议的更简洁的方法了。非常感谢。 - Bungle
1
@Bungle,你只能使用this来引用公共属性。例如,如果$slider是私有的,你可以将第一个this.$slider替换为var $slider,第二个替换为$slider - Matthew Flaschen
谢谢,马修 - 很好知道!在这种情况下,我实际上打算让所有属性都是公共的。 - Bungle

23

不幸的是,不能。 {} 语法初始化了一个新对象,但在对象创建之前,它并没有分配给 carousel 变量。此外,this 值只能因函数调用而改变。如果你的“几个属性”都只依赖于 slider,那么你可以采用这样的方法:

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

谢谢,卡萨布兰卡!我喜欢你的方法,适用于大多数对象属性仅依赖于一两个其他变量的情况。对于我的用例,不幸的是,这并不适用,所以我认为马修·弗拉申的方法最终会更加优雅。再次感谢。 - Bungle

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接