【问题标题】:JavaScript nesting objectsJavaScript 嵌套对象
【发布时间】:2012-12-25 13:37:53
【问题描述】:

我有一个关于 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

【问题讨论】:

    标签: javascript oop prototype


    【解决方案1】:

    我会这样做:

    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. 松散耦合 - stats 对象不需要知道游戏对象。所以最好把它和游戏对象分开。如果您使用对象文字符号创建它(如@Bergi 所做的那样),那么 stats 对象可以访问游戏对象的私有成员(如果 stats 对象意外更改游戏对象的私有属性,这可能会适得其反)。
    4. 可读性 - 比较 @Bergi 的代码和我的代码。将统计数据和游戏对象分开使代码更易于阅读和理解。您只需看一眼代码,就可以确切地知道发生了什么。

    【讨论】:

      【解决方案2】:

      这样应该更合适

      function Game() {
        this.id;
        this.stats = "Hello";
        return this;
      }
      
      var a = new Game();
      alert(a.stats);
      

      基本上在您的情况下 stats is a local variable ,并且创建的对象不知道该变量。

      Check Fiddle

      【讨论】:

        【解决方案3】:

        是的,这正是要走的路。

        请注意,method() 中的 this keyword 将包含 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's Prototypal inheritance - Issues with nested objects

        【讨论】:

        • “var that = this”的目的是什么?我看到声明的变量,但从未使用过。
        • 请注意,var message = "hello"; this.nested_primitive = message; 将创建一个副本,而不是对象引用...
        • @Potatoswatter:“nested_primitive”对我来说没有多大意义。你到底是什么意思?
        • @Bergi 通过thisgame 更改值不会影响原始对象的varnested_object 的模式只适用于正确的对象,这对于新手来说可能是不直观的。 (你已经在另一个 answer 中解决了这个问题。)
        • @Potatoswatter:没有所谓的“原始对象”。 this(至少在这里)和game都是正确的对象。
        【解决方案4】:

        [编辑以回应下面的 cmets]

        这个怎么样:

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

        【讨论】:

        • return 语句是干什么用的?
        • @JaPerk14 如果您从构造函数返回一个值,它会覆盖返回this 的默认行为,因此不会使用prototype
        • 谢谢@JaPerk14 我没有注意到它被称为“新”。 (我通常使用功能性更强的样式,避免使用new,)我更改了上面的代码。
        【解决方案5】:

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

        function Game() {
            this.stats = { lives: 3 };
        };
        
        var a = new Game();
        -- a.stats.lives;
        

        但是,这可能很烦人,因为在Game 的实现中,您必须将stats 称为this.statsthis'es 加起来,当 this 引用错误的东西时可能会出现混淆,例如在 function(){} 表达式中。

        我喜欢的图案是这样的。它本质上是一个经典的 OO getter 函数。

        function Game() {
            var stats = { lives: 3 };
            this.stats = function() { return stats; };
        };
        
        var a = new Game();
        -- a.stats().lives;
        

        【讨论】:

        • “var stats”和“this.stats”有什么区别?我一直认为一个人应该覆盖另一个人的价值。这不是它的工作原理吗?
        • @JaPerk14 不,两个完全不同的变量。如果this.stats 存在但你写stats.lives = 3;,那是一个错误。创建var stats 不会向this 添加任何内容。
        • @Bergi 太棒了,我独立想出了它,但很高兴看到一个将 getter 称为“聪明”的参考:)
        【解决方案6】:

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

        【讨论】:

        • 如果您不知道自己在做什么,请注意Game.prototype。不要在没有适当警告的情况下宣传此选项。
        • 我同意。使用原型比使用this 更难理解。
        • 也可以,但是原型上的嵌套对象有不同的行为——这是你需要注意的
        猜你喜欢
        • 2013-08-02
        • 1970-01-01
        • 2021-01-15
        • 2022-01-20
        • 2020-11-30
        • 2020-12-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多