-1

我是 js 中的 oop 新手。我正在使用 Box2dWeb 开发 HTML5 游戏,我决定应该让它完全基于 oop。所以我在一个名为physics.js

(function(window) 
{
function Physics(element, scale){
//init world logic
    }

Physics.prototype.debug = function(){
           //debug draw logic
};

Physics.prototype.step = function(dt){
    //step logic
};

    //making this class(or object) visible on the global scope
    //so i can create vars of this type anywhere in the application
window.Physics = Physics;
}(window));

现在我有一个主game.js文件,我在其中初始化了我所有的游戏物理、图形、资产等。以下是内容:

(function(){
 function init(){
    var physics = new Physics(document.getElementById("b2dCanvas"), 30);
    console.log(physics);
    physics.debug();
}
window.addEventListener("load", init);
 }());

这个文件,初始化我的物理对象没有任何问题。最终这就是我想要的。伟大的!但是,在此之前,文件是这样的,没有这个init()功能。

(function(){

    var physics = new Physics(document.getElementById("b2dCanvas"), 30);
    console.log(physics);
    physics.debug();
 }());

这显然引发了错误Uncaught TypeError: Cannot call method 'getContext' of null。这意味着,物理构造函数被调用(element此时自然为空),而我没有调用它。这怎么可能?我的自执行函数game.js应该已经初始化了Physics对象吧?我错过了什么?

4

4 回答 4

2

您的脚本在 HTML 被完全解析之前运行,并且在您的画布元素被添加到 DOM 之前。添加时window.addEventListener("load", init);,您在触发 window.onload 事件时使其运行。在那一刻,DOM 被完全解析。

在现代浏览器中,您也可以将其替换为

document.addEventListener("DOMContentLoaded", init);

该事件将在 DOM 准备就绪时触发,但不会等待图像等其他资源(与 onload 不同)。

或者,只需在关闭 body 标记之前添加所有脚本。那时,正文中的每个 HTML 标记都已经插入到 DOM 中。

于 2013-03-04T20:05:02.647 回答
1

这意味着,物理构造函数被调用(此时元素自然为空),而我没有调用它。这怎么可能?

因为你正在调用它,使用以下语法:

(function(){...}());
                ^^
               call

当脚本被解析为正常页面脚本解析的一部分时,它将调用该函数,并且不会等待文档/DOM 准备好供您操作。您将需要使用某种文档“加载”侦听器,或者删除该特定语法并在确定 DOM 准备好时手动调用该函数。

于 2013-03-04T20:04:30.110 回答
0

该错误与物理对象未准备好无关。它与其中的代码有关,它试图在调用代码时引用不在页面上的元素。

你打电话很简单

document.getElementById("b2dCanvas")

在元素加载到页面之前。当 getElementById 没有找到任何东西时,它返回 null。

那么,如果您要检查它,您的代码会是什么样子

var physics = new Physics(null, 30);

并且元素为空

function Physics(element, scale){  
    var ctx = element.getContext("2d");  //<-- where the error occurs since element is null

因此错误:Uncaught TypeError: Cannot call method 'getContext' of null.

当您侦听 load 事件时,这意味着元素在那里,因此它可以毫无问题地加载。其他处理方法是将脚本添加到页面底部。

于 2013-03-04T20:04:06.083 回答
0

我的猜测是您在 DOM 准备好之前调用了该函数。将脚本包含在代码的底部,或者甚至更好地将所有初始化包装为一个窗口加载侦听器。

于 2013-03-04T20:04:48.340 回答