1

Here's my code, I'm experimenting stuff with canvas:

function Map(){

    this.personnages = new Array();

}

Map.prototype.addPersonnage = function(perso) {

    this.personnages.push(perso);
    console.log(this.personnages);

}

Map.prototype.drawMap = function(){

    console.log(this.personnages);

    for(var i = 0; i < this.personnages.length; i++) {
        this.personnages[i].dessinerPersonnage(context);
    }

}

The thing is : the first console.log prints the array just fine, but the second one (in Map.prototype.drawMap) returns "undefined" (therefore the loop can't be executed)... I guess that functions are called in a correct order :

var canvas = document.getElementById('main');
var ctx = canvas.getContext('2d');    
var tilesetImage = new Image();
tilesetImage.src = 'img/tileset.png';

var map1 = new Map();
var player = new Personnage("img/player.png", 7, 14, DIRECTION.BAS);
map1.addPersonnage(player);
tilesetImage.onload = map1.drawMap;

I'm kinda new here, please tell me if I gave enough elements. Thanks in advance, any little help appreciated!

astrodedl
  • 200
  • 3
  • 8

5 Answers5

2
tilesetImage.onload = map1.drawMap;

When map1.drawMap is executed, this refers to tilesetImage, the target of the load event. If you want to keep this referring to map1, you can use Function.bind:

tilesetImage.onload = map1.drawMap.bind(map1);

Or you can use a function that calls drawMap on map1 directly.

tilesetImage.onload = function () { map1.drawMap() };

For more information on this, please see this question.

Community
  • 1
  • 1
poke
  • 307,619
  • 61
  • 472
  • 533
1

When you do

map1.drawMap();

inside the drawMap function, this will refer to map1 object, which has personnages variable. That is why map1.addPersonnage(player); works properly.

Now, you are simply assigning drawMap function to tilesetImage.onload. So, when tilesetImage.onload is invoked, this will refer to tilesetImage which will not have personnages variable.

That is why the second console.log prints undefined.

To fix this problem, you should bind the map1 object to this object like this

tilesetImage.onload = map1.drawMap.bind(map1);
thefourtheye
  • 206,604
  • 43
  • 412
  • 459
0

The value of this is not the instance when passing instance function as event handler

Pass a closure or use bind

Its all explained in the following answer https://stackoverflow.com/a/16063711/1641941 under the this variable

Community
  • 1
  • 1
HMR
  • 30,349
  • 16
  • 67
  • 136
0

You call the methode drawMap with help of tilesetImage which is an Image-Object that does not have got the attribute personnages, unless you define it.

This code might help you:

tilesetImage.onload = map1.drawMap.bind(map1);

Hope this helps a little bit.

Blauharley
  • 3,936
  • 6
  • 25
  • 45
0

here, take the bush function i wrote. it works for standard arrays and associative arrays and jep it also works for Objects to add key/value pairs. also added instanceof defineproperty that checks if we have a fresh browser or an old explorer, if so it wont make every array or object you create a child.

    // DIE BUSCHFUNKTION: OBJEKT.BUSCH FUNKTION
// Object/Array.bush() native function that adds a new
// arrayelement to the beginning of the specified.
// Included it also to work for Object Stacks key/value
// pairs and is 2x to 10x times better then default push
if(!('bush' in Object.prototype)){/****/
if((Object.defineProperty instanceof Function))
{(Object.defineProperty(Object.prototype,'bush',{ //modern
  enumerable:false,configurable:true,value:function(key,value)
  {if(key&&value){return this[key]=value;}
     return this[this.length]=key;}}))}
   else{Object.prototype.bush=function(key,value) // compatible
    {if(key&&value){return this[key]=value;}
     return this[this.length]=key;}}};
scorp1984
  • 1
  • 2