Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/380.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 我该如何包装我的发动机?_Javascript_Web Applications - Fatal编程技术网

Javascript 我该如何包装我的发动机?

Javascript 我该如何包装我的发动机?,javascript,web-applications,Javascript,Web Applications,我正在为Javascript创建一个游戏引擎,或者更像是一个有用类和函数的大型库。我计划将其用于服务器端和客户端的一些科学模拟,因此功能范围将非常广泛,但它始终围绕虚拟世界(例如游戏)运行 不过,我不知道该如何总结。如果我只提供所有的类,它会污染全局名称空间,这是非常糟糕的。我能把所有的东西都放在一个对象中,作为名称空间吗?框架本身应该是一个可以实例化的类吗 如果选择了后面的选项,如何处理类(构造函数)中的类 我认为你不需要甚至不应该这样组织你的课程。即使场景和引擎类是相关的,场景类也不必是渲染

我正在为Javascript创建一个游戏引擎,或者更像是一个有用类和函数的大型库。我计划将其用于服务器端和客户端的一些科学模拟,因此功能范围将非常广泛,但它始终围绕虚拟世界(例如游戏)运行

不过,我不知道该如何总结。如果我只提供所有的类,它会污染全局名称空间,这是非常糟糕的。我能把所有的东西都放在一个对象中,作为名称空间吗?框架本身应该是一个可以实例化的类吗

如果选择了后面的选项,如何处理类(构造函数)中的类


我认为你不需要甚至不应该这样组织你的课程。即使场景和引擎类是相关的,场景类也不必是渲染的子类。改为使用平面类层次结构,这样更易于维护和扩展

最后,您确实应该将所有这些类放在同一名称空间下,以免污染全局名称空间

// Define the namespace only if it doesn't already exist. That
// way you can split the definition of your classes in various
// files, without having to worry in which order they are loaded.
if (typeof gameEngine === 'undefined') gameEngine = {};

gameEngine.Engine = function()
{
    this.someVar = 4;
}

gameEngine.Scene = function()
{
    this.entities = [];
}

// Add a new function to define which
// scene the Engine should render:
gameEngine.Engine.prototype.setScene = function(scene)
{
    this.scene = scene;
}

gameEngine.Engine.prototype.render = function()
{
    // render this.scene
}

我更喜欢使用有时被称为“(…模式)的方法。它看起来像:

var Engine = (function($)
{
    $ = $ || {};
    var someVar = 4;

    $.Scene = function()
    {
        this.entities = [];
    }

    $.Scene.prototype.render = function()
    {
        // this function can access someVar just fine because of JavaScript's scoping rules
    }

    return $;
})(Engine);
这使用了被称为立即调用的函数表达式(以下称为IIFE)在引擎对象内形成闭包。由于,
someVar
可供IIFE中定义的任何函数访问。然而,这意味着,如果函数想要引用您在IIFE中定义的
someVar
,那么它就不能定义自己的
someVar

魔力来自于return语句。您可以看到返回了一个对象,在这个对象中,您必须定义任何您想成为“公共”的内容

然后可以通过
Engine.Scene
访问构造函数、实用程序方法等,这可以很好地为代码命名

对于
$
参数,这样您就可以将
引擎
传递给每个文件中的函数,添加一些方法/属性/构造函数(或者创建一个新的方法/属性/构造函数,如果它不存在),然后将返回值传递给另一个IIFE以进行进一步扩展

这是许多流行JavaScript框架中使用的方法,包括、和


scene.js:

var Engine = (function ($) {
  // this creates a new object if Engine is undefined in the 
  // invocation below, and keeps the old object otherwise.
  // alternatively: if ($ === undefined) { $ = new Object; }
  $ = $ || {};

  $.foo = "foo";
  $.Scene = function () {
    // blah blah
  }

  // Engine holds either a newly created object,
  // or the old one if it was already defined
  return $;
})(Engine);
sprite.js:

var Engine = (function ($) {
  $ = $ || {};

  $.Sprite = function () {
    // totally works
    this.bar = $.foo;
  }

  return $;
})(Engine);
然后,您可以将它们与以下内容一起使用:

<script type="text/javascript" src="bar.js"></script>
<script type="text/javascript" src="foo.js"></script>
<script type="text/javascript">
  var mySprite = new Engine.Sprite;
  var myScene = new Engine.Scene;
</script>

var mySprite=新引擎.Sprite;
var myScene=newengine.Scene;

你可以用你喜欢的任何东西来代替
$
$$
很常见,或者你可以很聪明。它只是您要添加到的全局对象的占位符。

那么您基本上是在建议第一个选项?另外,没有渲染器对象,
场景
有一个
渲染
方法。@贝恩,是的,我想这是第一个选项,您可以简单地定义一个名称空间并将所有类放在它下面。好的,如果
场景
进行渲染,则不需要额外的方法。一般来说,其思想是使用setter(如示例中所示)来注入依赖项。它可以使框架保持更灵活。你也可以使它与支持库如requirejsI兼容。我知道这是如何工作的,但我不使用它,因为每个类都需要一个单独的文件。我不能在一个文件中放入几千行代码。请您创建另一个代码框,并演示多文件技术。有很多具体的方法可以做到这一点,但我已经介绍了我使用的方法。如果需要显式依赖项跟踪,还可以使用closure或requirejs之类的框架。
<script type="text/javascript" src="bar.js"></script>
<script type="text/javascript" src="foo.js"></script>
<script type="text/javascript">
  var mySprite = new Engine.Sprite;
  var myScene = new Engine.Scene;
</script>