Jump to content

Help with sprite


m_spz
 Share

Recommended Posts

Hello, im trying to call an function when i press a button in html and it throw me this error:

Uncaught TypeError: Cannot read property 'sprite' of undefined
    at showMessage (init.js:105)
    at xd(init.js:121)
    at HTMLDivElement.onclick ((index):1)

 

The function is this:

function xd(){
console.log("clicked0");
showMessage();
console.log("clicked1");
}
 
function showMessage(){
this.add.sprite(725, 275, 'message');
}
Link to comment
Share on other sites

Hey there @m_spz, welcome to the forums!

You're having an issue with scoping in JS, and the use of context. It can be a little tricky, and is sometimes unexpected if you come from other languages (particularly classical languages).

`this` is a context in which functions execute. In your case `this` is applied by `addEventListener` by default to the HTML element to which it is attached, i.e.

var el = document.querySelector('#myElement')
el.addEventListener('click', function () {
  console.log(this)
})

// <div id='myElement'>...</div>

HTML elements do have quite a few methods (functions) and members (data) attached to them. You are trying to access a function (`sprite`) on an object (`add`). As `this` is not what you're expecting (unless you've done something not shown it'll be the HTML element) the object `add` does not exist (it is undefined), and the error is telling you that the JS engine is trying to access a function (`sprite`) on the undefined object, which throws an error.

There is some info here and here from MDN on JS scoping, there are a couple of reasons these don't mention the `this` keyword.

You can explicitly set a context for a function, see the docs for `.bind`. There are sister functions `.call` and `.apply`, but `.bind` is probably going to make your program operate how your mental model expects. There are pros and cons to this.

Something common is to do something like the following (note that I'm not suggesting this is a good or bad pattern, only that it is common):

var el = document.querySelector('#myButton')

var entity = {
  name: 'Dave',
  say: function () {
    console.log(this.name)
  }
}

el.addEventListener('click', entity.say.bind(entity))

This binds the function `say` with the object `entity`. If you come from a classical language this might exhibit the behaviour you are expecting.

By binding the `entity` object `this` becomes the `entity` object and we can access `this.name` and get the value we expect. If you omit the `.bind` you won't get 'Dave' back for name.

Note that `.bind`ing creates a new function, this isn't specifically attached to the `entity` object, it is contextually bound. Depending on what you are doing this may not matter too much but when you start having vast arrays of objects it can become important because you are creating lots of new functions rather than passing around a pointer to a single function.

Link to comment
Share on other sites

 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...