Javascript 对js作用域和外部类的质疑

Javascript 对js作用域和外部类的质疑,javascript,oop,box2dweb,Javascript,Oop,Box2dweb,我是js中oop的新手。我正在使用Box2dWeb开发一款HTML5游戏,我决定让它完全基于oop。所以我在一个名为physics.js的单独文件中创建了一个类似这样的物理类 (function(window) { function Physics(element, scale){ //init world logic } Physics.prototype.debug = function(){ //debug draw logic }; Physics.p

我是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();
 }());

这显然抛出了错误
uncaughttypeerror:cannotcallmethod'getContext'of null
。这意味着,物理构造函数被调用(此时
元素
自然为空),而我没有调用它。这怎么可能?我在
game.js
中的自动执行函数应该初始化
物理
对象,对吗?我错过了什么

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

你打电话很简单

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
函数物理(元素、尺度){
var ctx=element.getContext(“2d”)//
这意味着,物理构造器被调用(而且是自然调用的)
元素在这一点上是空的),而我没有调用它。这是怎么回事
可能吗

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

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

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

My g原因是您在DOM准备就绪之前调用函数。将脚本include放在代码底部,或者更好的做法是将所有初始化都包装到窗口加载侦听器中。

在HTML完全解析之前,以及在画布元素添加到DOM之前,您的脚本正在运行。当您添加
窗口时。addEventListener(“load”,init);
,您让它在触发window.onload事件时运行。此时,DOM被完全解析

在现代浏览器中,您还可以用

document.addEventListener("DOMContentLoaded", init);
该事件将在DOM就绪时触发,但不会等待其他资源,如映像(与onload不同)


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

听起来好像op已经知道,“正在调用物理构造函数(此时的元素自然为null)”@Madbreaks问题是OP不理解页面生命周期。我不认为这是真的。我认为OP不理解他/她使用的函数语法,基于(文字)问题被问到。哦,好吧,op没有接受我们的任何一个答案。:)正如你已经说过的,
元素
null
。在你的
物理
构造函数中,你试图对它调用一个方法,这显然是不可能的。@Bergi这不是op想要的asked@Bergi我已经知道了。我对e的顺序更感兴趣
Physics
类的执行和范围。
game.js
Physics.js
都是自执行函数。也许,在
标记中声明脚本的顺序很重要?@jaykumarak它与其他对象中的代码无关,这是因为您在引用元素之前引用了它加载。简单明了。了解页面生命周期。DomReady、load等。
load
事件在我的代码中起到了关键作用。当我遵循
game.js
的后一个片段和物理类作用域时,我很关心执行顺序。但是你的提示很有意义:等待dom完全加载:)谢谢:)@jaykumarark这应该是您要查找的。因为上一个代码示例中的函数是自动执行的,所以物理被实例化。因为目标对象还不在DOM中,所以它在查询时返回null。@Jaykumarak执行的顺序是源代码的顺序。立即调用的函数将在t之后立即调用继承人定义。如果一行中有两个继承人(或两个