2

I'm working with PixiJS but my question is very general. I created a constructor (1) and within that constructor (1) I call another constructor (2). I now need to access some methods of constructor (2) from the constructor (1) but I alway get the output 'Cannot read property 'renderer' of undefined'. What am I doing wrong?

Call constructor 1 and it's method 'animate':

stage3 = new site3();
requestAnimationFrame(stage3.animate);

Constructor 1:

function site3() {
    this.fullstage = new fullscreenstage("intimg");

    this.snowfrontblur = new PIXI.BlurFilter();
    this.snowfrontblur.blurX = 5;
    this.snowfrontblur.blurY = 5;

    this.snowfront = SpriteFromImage("resources/img/snow.png",0,0,0.5,0.5);
    this.fullstage.stage.addChild(this.snowfront);

    this.snowfront.filters = [this.snowfrontblur];
}

site3.prototype.animate = function() {
    this.fullstage.renderer.render(this.fullstage.stage);
    requestAnimationFrame(this.animate);
};

Constructor 2:

function fullscreenstage(cavansid){
    this.renderer = new PIXI.WebGLRenderer(ww, wh, null, true);
    document.getElementById(cavansid).appendChild(this.renderer.view);
    this.interactive = true;
    this.stage = new PIXI.Stage(0x000000, this.interactive);    
}

2 Answers2

1

The problem you face has to do with how JS binds the context to a function: it's an ad-hoc binding. The context (represented by the this keyword) can vary depending on how and where a function object is invoked.
In this statement:

requestAnimationFrame(stage3.animate);

You pass a reference to the animate function object to requestAnimationFrame, but in doing so, the function looses its context, hence when you call that function within requestAnimationFrame, the this keyword will not be bound to stage3. The easiest fix is to pass the entire object:

requestAnimationFrame(stage3);
//in requestAnimationFrame:
function requestAnimationFrame(instance)
{
    instance.animate();
}

In that case, this.fullstage.renderer.render(this.fullstage.stage); inside the animate function will resolve correctly.

An other option is to bind the context to the function in a more permanent way:

site3.animate.bind(site3);

I'll add some links to details on JS's context binding over time, starting with:

this answer of mine make sure to check the links at the bottom

JavaScript "this" keyword and Closure Compiler warnings

Community
  • 1
  • 1
Elias Van Ootegem
  • 74,482
  • 9
  • 111
  • 149
0

I solved it by creating an reference to the own object at the beginning of site3() and implementing the animate method into the constructor:

function site3() {
    var that = this; //creating the reference
    this.fullstage = new fullscreenstage("intimg");

    this.snowfrontblur = new PIXI.BlurFilter();
    this.snowfrontblur.blurX = 5;
    this.snowfrontblur.blurY = 5;

    this.snowfront = SpriteFromImage("resources/img/snow.png",0,0,0.5,0.5);
    this.fullstage.stage.addChild(this.snowfront);

    this.snowfront.filters = [this.snowfrontblur];

    this.animate = function(){
        that.fullstage.renderer.render(that.fullstage.stage);
        requestAnimationFrame(that.animate);    
    }
}
  • defining a method inside a constructor is a terrible idea... it defeats the whole point of constructors, really: it creates a new function object for each instance. You might as well construct an object literal in the function and return that. that would be better as omitting the `new` keyword with this function clutters the context – Elias Van Ootegem Jun 26 '14 at 09:55