我是js的新手。我正在使用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);
}());
这个文件初始化我的Physics对象没有任何问题。最终这就是我想要的。大!但是,在此之前,文件是这样的,没有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
对象吗?我错过了什么?
答案 0 :(得分:2)
在完全解析HTML之前,以及在将canvas元素添加到DOM之前,您的脚本已在运行。当您添加window.addEventListener("load", init);
时,您在触发window.onload事件时运行它。那时,DOM被完全解析了。
在现代浏览器中,您也可以用
替换它document.addEventListener("DOMContentLoaded", init);
该事件将在DOM准备就绪时触发,但不会等待其他资源(如图像)(与onload不同)。
或者,只需在关闭body标签之前添加所有脚本。此时,正文中的每个HTML标记都已插入DOM中。
答案 1 :(得分:1)
这意味着,正在调用物理构造函数(当然也是如此) 此时元素为null)没有我调用它。怎么样 可能的?
使用以下语法 调用它:
(function(){...}());
^^
call
当脚本被解析为正常页面脚本解析的一部分时,它将调用该函数,并且不会等待文档/ DOM准备好您进行操作。你想要使用某种文档'load'监听器,或者删除那个特定的语法,并在你确定DOM准备就绪时手动调用该函数。
答案 2 :(得分: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事件时,这意味着元素在那里,所以它加载没有问题。处理它的其他方法是将脚本添加到页面底部。
答案 3 :(得分:0)
我的猜测是你在DOM准备好之前调用了这个函数。将脚本include包含在代码的底部,甚至更好地将所有init包装成一个窗口加载监听器。