子类的子类?

时间:2015-02-05 20:44:25

标签: javascript

我一直在编写游戏引擎,我想重新组织我的代码以使其更加模块化。目前,我有一个名为Isometric的主函数,它接受画布来绘制。

var iso = new Isometric('canvas');

到目前为止一切顺利。接下来,我有.newMap()来创建新地图。

var map = iso.newMap(10,1,10); // Creates 10x1x10 map

但是,我想改变它,因为.map属性可能会有一些混淆(因为这会返回一个名为map 的数组)。

我希望语法看起来像这样:

iso.Map.create(10,1,10);

所以我尝试过这样的事情:

function Isometric(id) {
    this.Map = function() {
        this.create = function() {
        }
    }
}

但是当我去访问它时,我意识到第二级this仍然指的是同一个第一级。所以,我无法创建Map对象的子类。

我已经看了几种不同的方法,但没有一种方法有明确的例子,我也无法让它们发挥作用。

其中,我知道您可以使用prototypeObject.create(),但我没有取得多大成功。

我该怎么做?

我的另一个解决方案是做这样的事情:

function Isometric('id') {
    this.Map = {
        'create': function() { },
        'load': function() {}
    }
}

然后像

一样访问它
iso.Map['create'];

但我根本不喜欢这样。这样做有什么干净的方法吗?

我的主要兴趣是在.map中使用第三级方法..create()的示例。如果你能提供我尚未找到的与我的问题相关的文件,那就太好了。但即使是mozilla文档似乎也无济于事。

2 个答案:

答案 0 :(得分:1)

我认为在这里做的恰当的事情是在 Isometric 构造函数下命名 Map 构造函数。以下是你可以采取的措施。

function Isometric(id) {
  this.id = id;
}

Isometric.prototype = {
  constructor: Isometric,

  test: function() {
    return "I'm an instance of Isometric.";
  }
};

这里我们执行命名空间并向Map构造函数添加create()辅助方法以创建其实例。

Isometric.Map = function Map(x, y, z) {
  this.x = x;
  this.y = y;
  this.z = z;
}

Isometric.Map.prototype = {
  constructor: Isometric.Map,

  test: function() {
    return "I'm an instance of Isometric.Map.";
  }
};

// Helper method to create `Map` instances
Isometric.Map.create = function create(x, y, z) {
  return new Isometric.Map(x, y, z);
};

<强>用法

var iso = new Isometric('id123');
var map = new Isometric.Map(0, 7, 99);
var map2 = Isometric.Map.create(1, 2, 3);

iso.test(); //=> "I'm an instance of Isometric."
map.test(); //=> "I'm an instance of Isometric.Map."
map2.test(); //=> "I'm an instance of Isometric.Map."

命名空间

重要的是要注意我们刚刚执行的命名空间可以防止与ES6中的新Map类发生冲突(新JS版) - 更多关于ES6地图的信息:{ {3}}。

话虽如此,将代码命名为一个主要对象(你可以称之为app )并且只在全局范围内使用该命名空间总是很重要。

在您的情况下,您可以执行以下示例:

;(function(win) {
  // Isometric
  function Isometric(id) {
    this.id = id;
  }

  Isometric.prototype = {
    constructor: Isometric,

    test: function() {
      return "I'm an instance of Isometric.";
    }
  };


  // Map
  function Map(x, y, z) {
    this.x = x;
    this.y = y;
    this.z = z;
  }

  Map.prototype = {
    constructor: Map,

    test: function() {
      return "I'm an instance of Isometric.Map.";
    }
  };

  // Helper method to create `Map` instances
  Map.create = function create(x, y, z) {
    return new Map(x, y, z);
  };


  // Namespace Map under Isometric
  Isometric.Map = Map;


  // Expose globally
  // --------------------
  win.app = {
    Isometric: Isometric
  };
}(this));

示例:

var nativeMap = new Map();
nativeMap.set('name', 'joe'); //=> {"name" => "joe"}

var myMap = new app.Isometric.Map(33, 7, 99);
myMap.test(); //=> "I'm an instance of Isometric.Map."

// Native map wasn't affected (good)
nativeMap.test(); //=> TypeError: undefined is not a function

答案 1 :(得分:0)

我会将其他答案保留为接受,因为它更详细,甚至告诉我我的代码可能会被原样弃用。

话虽这么说,我想重新讨论Felix King的解决方案。我将想出一种结合两种想法的方法(使用命名空间和使用Felix),但这里有部分解决方案。

function Isometric(id) {
    this.Map = function() {
        this.create = function() {
            return 5;
        };
    };
}

这就是我的设置。 5只是一个任意值。

 var iso = new Isometric(); // New instance of Isometric()
 var mapping = new iso.Map(); // Access to Iso's mapping functions
 var map = mapping.create(); // Should return a map array 

 console.log(map); // Prints 5

对于关注此事的任何人,如果您想了解我最终如何实现它,那么请参阅我的Github项目:https://github.com/joshlalonde/IsometricJS

我将在本周末的某个时间播放代码。

再次感谢大家的帮助!祝所有试图做类似事情的人好运。