Reputation: 172
I have a game in JS that starts on body onload and then uses cursor position which is updated on body onmousemove event.
First, I had global variables and separate functions in my JS file and I called them like this:
<body onload="startGame()" onmousemove="setMousePosition(event)">
It worked fine but I wanted to get rid of global variables. I have enclosed everything into Game class but now I don't know how to call class methods from different html events. The only solution I can think of is to declare game object globally but then I will still have to use a global variable (which is better than a whole bunch of them but still...):
HTML:
<body onload="game = new Game()" onmousemove="game.setMousePosition(event)">
JS:
class Game {
constructor() {
// do the thing
}
setMousePosition(e) {
// do the thing
}
}
let game;
Is there any elegant way to call class methods from different html events without a global variable?
Upvotes: 0
Views: 176
Reputation: 1114
Heres an approach that avoids globals and hopefully looks elegant enough.
<!doctype html>
<html>
<head>
</head>
<body>
<script type="application/javascript">
// Self executing anonymous function that hides any globals declared in it
void function() {
"use strict"; // Turns on strict mode, which discourages badly written JS
class Game {
constructor(id) {
this.id = id;
}
setMousePosition(e) {
console.log(this.id,e.clientX,e.clientY);
}
}
// Overload window.onload
window.onload = function() {
var game = new Game(5);
/*
To understand how this works it helps to know
how Javascript classes work
classes are just made up of two components, a constructor function
that sets up properties for objects when you call the class with 'new'
and a prototype object, think of it as a set of values that all instances
of the class share
e.g.
class A {
constructor() {
}
doThing() {
}
}
does the exact same thing as
function A() {
}
A.prototype = {
doThing: function() {
}
};
every function in javascript has it's own 'this' variable
, when a function in a class is called 'this' is set to
the object your calling it with.
the last part is .bind(), its a method you can call on any function.
It creates a copy of the function but the 'this' variable is always set to
a specific object, in this game it's 'game'
*/
window.onmousemove = Game.prototype.setMousePosition.bind(game);
}
}();
</script>
</body>
</html>
Upvotes: 0
Reputation: 4594
Adding event listeners via HTML attributes is actually an old and unrecommended way of doing it, for exactly the reason you're encountering: you need globals. The modern approach is to use no HTML for events, instead using JavaScript to first look up the element you want then add an event listener to it with the function addEventListener
. So, in your case, you'd have code like the following in your game init code.
document.body.addEventListener('mousemove', setMousePosition);
Upvotes: 1