JavaScript嵌套对象

4

我有一个关于JavaScript的问题。目前我正在使用类似下面代码的代码:

function Game() {

}

我想要嵌套对象,这样我就可以像这样访问它们:
var a = new Game();
a.nested_object.method();
a.nested_object.property;

我该如何做到这一点?我应该使用函数还是{}?或者这并不重要?下面的代码是我所指的示例代码。
function Game() {

this.id;

var stats = {};

}

就像我之前所说的那样,我可以这样访问统计数据吗:

var a = new Game();
a.stats
6个回答

6
我会这样做:
function Game() {
    this.id;
    this.stats = new Stats(this);
}

function Stats(game) {
    this.property;
    this.method = method;

    function method() {
        this.property;
        game.id;
    }
}

var game = new Game;
game.stats.method();

以下是原因:
  1. 关注点分离 - 游戏构造器可以完全专注于游戏逻辑,而统计构造器则仅集中于游戏的统计信息。
  2. 模块化 - 您可以将游戏构造器和统计构造器放在两个不同的文件中。这使您可以分别处理它们,并使项目更易于管理。
  3. 松耦合 - 统计对象不需要了解游戏对象。因此最好将其与游戏对象分开。如果您使用对象文字符号创建它(如@Bergi所做),则统计对象可以访问游戏对象的私有成员(如果统计对象意外更改游戏对象的私有属性,则可能会产生反作用)。
  4. 可读性 - 比较@Bergi的代码和我的代码。分离状态和游戏对象使代码更易于阅读和理解。您可以一眼看到代码,并知道正在发生什么。

2

是的,这正是正确的方法。

请注意,在您的method()中,this关键字将保存nested_object,而不是您的Game实例。您只能通过使用指向变量的引用来获取它的引用:

function Game() {
    var that = this; // the Game instance
    this.id = …;
    this.nested_object = {
        property: "nested!",
        method: function() {
            this.property; // nested! (=== that.nested_object.property)
            that.id // the game property
        }
    };
}
var game = new Game;
game.nested_object.method();

因此,在原型上嵌套对象(其中没有包含实例的变量)很少有意义 - 请参见Crockford的原型继承 - 嵌套对象的问题


“var that = this”的目的是什么?我看到变量被声明了,但从未被使用过。 - JaPerk14
请注意,var message = "hello"; this.nested_primitive = message; 会创建一个副本,而不是对象引用... - Potatoswatter
@Potatoswatter:“nested_primitive”对我来说没有太多意义。你具体是什么意思? - Bergi
@Bergi 通过 thisgame 更改值不会影响原始对象的 var。使用 nested_object 模式仅适用于正确的对象,这可能对新手来说不直观。(您在另一个答案中已经部分解决了这个问题。) - Potatoswatter
@Potatoswatter:不存在“原始对象”这样的东西。this(至少在这里)和game都是适当的对象。 - Bergi
@Bergi 是的,即使有了更多的经验,我也会忘记对象引用和整数一样原始。无论如何,getter/setter惯用语在避免尝试 object.property = something; 时产生混淆方面效果很好。为什么不像你的其他答案那样在这里推荐呢? - Potatoswatter

0

[根据下面的评论进行编辑]

这样怎么样:

function Game() {

    this.nested_object = {
        method: function () {
            return 'method return value';
        },

        property: 'property value'
    };

};

var a = new Game();
alert( a.nested_object.method() );
alert( a.nested_object.property );

返回语句的作用是什么? - JaPerk14
如果您从构造函数中返回一个值,那么它会覆盖返回 this 的默认行为,因此 prototype 不会被使用。 - Potatoswatter
谢谢@JaPerk14,我没有注意到它是用“new”调用的。(我通常使用更具功能性的风格,并避免使用new),我已经更改了上面的代码。 - Eamonn O'Brien-Strain

0

只需在构造函数中创建嵌套对象即可。

function Game() {
    this.stats = { lives: 3 };
};

var a = new Game();
-- a.stats.lives;

然而,这可能很烦人,因为在实现 Game 时必须将 stats 称为 this.statsthis 的数量会增加,当 this 指向错误的对象时,例如在 function(){} 表达式中,可能会引起混乱。
我的首选模式如下所示。它本质上是一个经典的面向对象的 getter 函数。
function Game() {
    var stats = { lives: 3 };
    this.stats = function() { return stats; };
};

var a = new Game();
-- a.stats().lives;

“var stats”和“this.stats”有什么区别?我一直认为其中一个应该会覆盖另一个的值。但事实真的是这样吗? - JaPerk14
@JaPerk14 不对,这是两个完全不同的变量。如果this.stats存在但你写成stats.lives = 3;,那就是一个错误。创建var stats并不会给this添加任何东西。 - Potatoswatter
@Bergi 很棒,我独立想出了这个方法,但看到有参考称getter为“聪明”的确不错 :) - Potatoswatter

0

这应该更合适

function Game() {
  this.id;
  this.stats = "Hello";
  return this;
}

var a = new Game();
alert(a.stats);

基本上在你的情况下,stats是一个局部变量,而创建的对象对该变量一无所知。

查看Fiddle


0
将“嵌套”内容添加到thisGame.prototype中。

如果你不知道自己在做什么,就要小心使用Game.prototype。未经适当警告,请勿宣传此选项。 - Bergi
我同意。使用原型比仅仅使用 this 更难理解一些。 - ericponto
这也可以,但是原型上的嵌套对象具有不同的行为 - 这就是你需要注意的。 - Bergi

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