BeachBum Posted September 25, 2014 Share Posted September 25, 2014 I feel like I'm just bad at Javascript to have to ask this question so please keep the disparaging remarks to a minimum. I have some game handling taking place on a server and being sent back to the game via JSON like this:Strategy.Game.prototype = { create: function() { this.greenGroup = this.add.group(); this.greenGroup.create(100,100, 'greenParticle'); this.getPath(); }, getPath: function() { $.getJSON("http://mysite.com/strategy/ajax/play.ashx", function (data) { console.log(JSON.stringify(data)); data.forEach(function(step)) { // need access to "game.greenGroup" here to create group entities and move existing ones. } }); }} There is more to the game obviously but hopefully you get the idea. I need to access game entities as I would normally have done with "this.greenGroup" but within the event handler the context has changed. I've tried pulling up the javascript console and seeing if I could track down how to reference the game object but I haven't found it. I can reference the class but it's not the actual working game object. Strangely the ways I've found to reference the game class the greenGroup is always undefined. Any idea where I've lost it? Link to comment Share on other sites More sharing options...
lewster32 Posted September 25, 2014 Share Posted September 25, 2014 This is usually done via local variables, saving the 'this' context so you can use it inside functions which steal 'this' for themselves:Strategy.Game.prototype = { create: function() { this.greenGroup = this.add.group(); this.greenGroup.create(100,100, 'greenParticle'); this.getPath(); }, getPath: function() { // Store 'this' (the state in this case) in a temporary local variable which will live // as long as anything in this function is executing, including functions within functions // - this is what you commonly hear referred to as 'closure' in JavaScript. var self = this; $.getJSON("http://mysite.com/strategy/ajax/play.ashx", function (data) { console.log(JSON.stringify(data)); data.forEach(function(step) { // self.greenGroup will be accessible here and anywhere else within 'getPath' // regardless of the amount of nested functions. }); }); }} Link to comment Share on other sites More sharing options...
BeachBum Posted September 25, 2014 Author Share Posted September 25, 2014 Thanks, that makes perfect sense. Something about working with Phaser has made me forget every bit of JS I ever knew, and it wasn't that much. Link to comment Share on other sites More sharing options...
begedin Posted September 26, 2014 Share Posted September 26, 2014 There is also another way. If you don't need the value of the "this" variable within the event handler, you can override it by using "bind()". In your case this would look like:Strategy.Game.prototype = { create: function() { this.greenGroup = this.add.group(); this.greenGroup.create(100,100, 'greenParticle'); this.getPath(); }, getPath: function() { $.getJSON("http://mysite.com/strategy/ajax/play.ashx", function (data) { console.log(JSON.stringify(data)); data.forEach(function(step)) { // need access to "game.greenGroup" here to create group entities and move existing ones. } }.bind(this)); }} By Adding ".bind(this) at the end, you have overridden the default value of this within the handler with the local value. If you don't need the local value, that's certainly on option. .bind() actually works with multiple arguments to, but I don't think that helps you here. for instance, if you used .bind(this, "bla") instead of just .bind(this), then the value of the "data" argument in the function will also change to "bla". .bind() is somewhat related to .call() and .apply(). Here's some reading that explains it in more detail: http://dailyjs.com/2012/06/25/this-binding/ Basically, .bind is used to say "when you later call this function, call it with the context I'm telling you to use". On the other hand, .call() and .apply() both mean "call this function now with this context" except there's a minor, but potentially important difference in how you specify the context between those two. Link to comment Share on other sites More sharing options...
lewster32 Posted September 26, 2014 Share Posted September 26, 2014 Realised that would probably cause a syntax error. Yeah, bind is another way to do this, but the one drawback is that if you have multiple nested functions, you'll have to add bind(this) to each one in order for 'this' to be passed through them, whereas a local variable will be accessible regardless. Link to comment Share on other sites More sharing options...
Recommended Posts