1

Can someone explain to me why I'm getting:

Uncaught TypeError: Cannot read property 'canvas' of undefined game.js:48

Uncaught TypeError: Cannot call method 'resize' of undefined game.js:4

It appears that for some reason this.stage is outside of the scope of the start function.

//index.js
var game;
function init()
{
    game    = new Game(document.getElementById('canvas'));
}
function resize()
{
    game.resize();
}

_

//game.js
function Game(canvas)
{
    this.canvas = canvas;
    this.stage  = null;
    this.loader = null;

    this.scaleCanvas();
    this.initCreateJS();
    this.loadAssets();
}

Game.prototype =
{
    resize: function()
    {
        this.scaleCanvas(this.canvas);
        this.level.resize(this.canvas.width, this.canvas.height);
        this.stage.update();
    },
    scaleCanvas: function()
    {
        this.canvas.width   = window.innerWidth;
        this.canvas.height  = window.innerHeight;
    },
    initCreateJS: function()
    {
        this.stage  = new createjs.Stage(this.canvas);
        createjs.Ticker.setFPS(30);
        this.stage.enableMouseOver(10);
        if(createjs.Touch.isSupported())
        {
            createjs.Touch.enable(this.stage);
        }
    },
    loadAssets: function()
    {
        manifest = [
            {src:"base.png", id:"base"},
            {src:"logo.png", id:"logo"}
        ];

        this.loader = new Loader(manifest, this.start);
    },
    start: function()
    {
        this.level = new Level(4,4,this.stage.canvas.width,game.stage.canvas.height);
        this.level.randomLevel();
        this.level.print();

        game.stage.addChild(this.level);
        game.stage.update();
    }
};
Community
  • 1
  • 1
Joshua Barnett
  • 4,055
  • 5
  • 24
  • 52

1 Answers1

0

Consider this:

var Foo = function(val) {
  this.val = val;
}
Foo.prototype.log = function() {
  console.log('Me haz ' + this.val);
}

Here we defined quite a simple class Foo: with a constructor function assigning its param to a property named val, and a single method log working on this value defined on Foo.prototype. Nothing extraordinary:

var foo = new Foo(42);
foo.log(); // Me haz 42

Now we define a simple function - that takes another function as a param, and calls this function. Something like this:

var fooCaller = function(cb) { cb(); }
fooCaller(function() { 
  console.log('I am called'); 
});

That was easy, right. But now things suddenly become complicated:

fooCaller(foo.log); // Me haz undefined

What? Obviously the correct function has been called (hence Me haz...) - but why this.val is undefined, and not 42 there? What has changed between calling foo.log directly and via caller func?

The difference is this. See, a unique feature of JavaScript is ability to switch contexts (the objects referred by this) for the same function without touching its body: only the way of invoking the function matters. There are two special methods that allow you to explicitly set value of this: Function.prototype.call and Function.prototype.apply. For example:

var bar = new Foo(34);
bar.log(); // Me haz 34
bar.log.call(foo); // Me haz 42

As you see, with call I've switched this object from bar (which val property is equal to 34) to foo. Note that it doesn't matter anymore which object 'owns' the function.


Now let's get back to your own code. This line...

new Loader(manifest, this.start);

... is obviously buggy: passing unbound object methods as callbacks is almost always a bad idea. In this case Loader eventually calls the function stored in this.start - but when it will, this will point to another object.

To prevent this, you need to bind the context: pass into new Loader another function which is defined by the current value of this. The easiest way is to use Function.prototype.bind:

new Loader(manifest, this.start.bind(this));

... which will basically create another function with fixed value of this (defined by its current value).


This, while quite extensive, is just a quick glance over how this functions in JavaScript (and not only in regards to functions, no pun intended )) ). I'd suggest checking this answer - and the articles mentioned in it, they sure will be quite enlightening. )

Community
  • 1
  • 1
raina77ow
  • 91,589
  • 12
  • 180
  • 210