我正在为 Javascript 创建一个游戏引擎,或者更像是一个包含有用类和函数的大型库。我计划将它用于服务器端和客户端的一些科学模拟,因此功能范围将相当广泛,但它始终围绕虚拟世界(例如游戏)展开。
不过,我不确定如何结束它。如果我只提供所有的类,它会污染全局命名空间,这是非常糟糕的。我可以将所有内容都放在一个对象中,充当命名空间吗?框架本身应该是一个可以实例化的类吗?
如果选择后一个选项,我如何处理类内部的类(构造函数)?
var Engine = function()
{
this.someVar = 4;
}
Engine.prototype.Scene = function()
{
this.entities = [];
//What if the scene object needs some classes that are in the engine? How does it get it's parent engine object?
}
Engine.prototype.Scene.prototype.render = function()
{
//"this" should now represent an instance of a scene. But how can I get someVar from the engine? How can I traverse up in the hierarchy of classes?
}
最佳答案
我更喜欢使用有时称为“revealing module”(...模式)的东西。看起来像:
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)在引擎对象中形成一个闭包。由于 JavaScript's handling of scope , someVar
可以被 IIFE 中定义的任何函数访问。然而,这意味着如果函数想要引用您在 IIFE 中定义的 someVar
,则任何函数都不能定义它自己的 someVar
。
魔法来自返回语句。您可以看到返回了一个对象,在这个对象中您必须定义任何您想要“公开”的内容。
然后可以通过 Engine.Scene
访问构造函数、实用程序方法等,这很好地为您的代码命名空间。
至于$
参数,这样你就可以将Engine
传递给每个文件中的函数,添加一些方法/属性/构造函数(或创建一个新的一个如果它不存在)然后将返回值传递给另一个 IIFE 以进一步扩展。
这是在许多 流行的 JavaScript 框架中使用的方法,包括 jQuery , dojo和 LimeJS
场景.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>
你可以用你喜欢的任何东西替换$
,$$
很常见,或者你可以很聪明。它只是您要添加到的全局对象的占位符。
关于javascript - 我应该如何包装我的引擎?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11718297/