Jump to content

this. usage


SIXII
 Share

Recommended Posts

Hi, guys. I'm trying to make a simple game using this tutorial

https://gamedevacademy.org/html5-phaser-tutorial-spacehipster-a-space-exploration-game/

Most i've done, but i still CANT understand how to use this, what does it means in this case and what happens if aint use it? I read some documentation about this, but it's not helps me well. I'm using [preload.js -> boot.js -> menu.js etc] template. Actually most of my code works but i know how important to understand this topic.

Here is some code sections whitch i can't understand.

//Why do we use this. here? What it points? Part of Preload.js
var Squares = Squares || {};
Squares.Preload = function(){};
Squares.Preload.prototype = {
    preload: function () {
              this.load.image('square', 'assets/images/square.png');
};

//Game.js
var Squares = Squares || {};
var lasted;
var borders;

Squares.Game = function(){};
Squares.Game.prototype = {
    create: function(){
       this.stage.backgroundColor = '#DCDCDC'; //not workig W/O this
       borders = this.game.add.group(); //why this here?

       var rect1 = borders.create(this.game.rnd.integerInRange(0, 50), this.game.rnd.integerInRange(0, 80), 'rect1');
       var recthor = borders.create(this.game.rnd.integerInRange(5, 65), this.game.rnd.integerInRange(175, 270), 'recthor');
       var rectver = borders.create(this.game.rnd.integerInRange(320, 415), this.game.rnd.integerInRange(10, 65), 'rectver');
       var square = borders.create(this.game.rnd.integerInRange(270, 380), this.game.rnd.integerInRange(190, 255), 'square');

        borders.setAll('this.body.collideWorldBounds',true); //setAll is not working W/O this
        borders.callAll('this.body.velocity',(100,100)); //not working at all
    },
    update: function() {
        }
};

 Help pls

Link to comment
Share on other sites

In JavaScript, "this" refers to the calling context of the function. Unlike other more traditional languages, in JS it is only possible to know the value of "this" within a function by examining, at runtime, what called the function. Let's look at some examples:

function blah() { console.log(this.cats); }

window.cats = 'dogs';

var o = { cats: 'pants' };

blah(); // console logs "dogs"
blah.call(o); // console logs "pants"
blah.call({ cats: 'horse' }); // console logs horse
o.thing = blah;
o.thing(); // console logs "pants"
var otherThing = o.thing;
otherThing(); // console logs "dogs"

Let's take it one-by-one:

1. First we define a function that logs the value "this.cats". Notice that this function is sitting by itself in the global namespace as "blah". There's no "this.blah()" to call it, it's just "blah".

2. Now I've assigned the value "dogs" to the property "cats" on window. "window" is the global object when JS is running in a browser. JS always has a global object.

3. Now I make a new object called "o". "o" also has a property "cats", but this time its value is "pants".

4. First I invoke "blah" by itself: "blah()". Since the call site is not associated with an object, "this" inside that function refers to the global object "window". That means the console is going to log "dogs".

5. Then I use the function "call" (a member of the Function prototype) to set the calling context of the "blah" function as that object I defined in step 3. Notice that I did not change "blah" at all, just how I called it. Now it'll log "pants" because the "o" object has the value "pants" as its "cats" property.

6. Then I use the function "call" to set the calling context to a throwaway object specified as an object literal. That object literal has a property named "cats" whose value is "horse". That's what is output on the console.

7. Now I assign the function "blah" as a property on the object "o". That property is named "thing". This is where things start getting weirder and where people *really* start messing up this. Both "blah" and "o.thing" refer to the same function, the same area in memory. But since the call site is different ("blah();" in one, "o.thing();" in the other) the value of "this" within the function will change.

8. Proving what I said in step 7 is true, running "o.thing();" logs out "pants" because "o" has a property named "cats" with the value of "pants".

9. Hammering the point home, I make a new name, "otherThing", that points to "o.thing". This is now an alias, another name, of the original function "blah".

10. Just like "blah", when I call "otherThing();" *by itself*, it logs "dogs" instead of "pants". Even though there's a line saying "otherThing = o.thing;" JS will not use "o" as the context for this function anymore. In Python, this function would be called unbounded.

Again, just to hammer this home, if you typed "blah === otherThing" the JS console would say "true". If you said "blah === o.thing" it would also say "true". The function isn't changing at all, only its call-site. That's the only thing that matters to functions in JS when figuring out what "this" means.

If you hand a function to a Phaser.Signal like this: "onEvent.add(this.blah);" you are stripping the call context from that function. The signal will not do what you probably expect. You can fix that two ways: you can use "bind" or you can pass the listener context.

In Phaser you *usually* pass the context. For signals, that looks like this: "onEvent.add(this.blah, this);" Notice that second argument is this? I've just told Phaser what context it should use when that signal fires.

You could also do this: "onEvent.add(this.blah.bind(this));" In Phaser you usually don't have to do this, but if you did you are creating an entirely new function that is forever bound to the value of "this" as it stood at runtime.

To return to the earlier example, "otherThing === o.thing === blah", right? But if I made one called "var boundThing = blah.bind({ cats: 'poop'});" then I have made an entirely NEW function (i.e. "blah !== boundThing") that is bound to that object with the value "poop" for the property named "cats".

This concept is fundamental to working successfully in JavaScript. It will come up again and again and trips up even very experienced developers.

Link to comment
Share on other sites


//  When a State is added to Phaser it automatically has the following properties set on it, even if they already exist:

this.game;      //  a reference to the currently running game (Phaser.Game)
this.add;       //  used to add sprites, text, groups, etc (Phaser.GameObjectFactory)
this.camera;    //  a reference to the game camera (Phaser.Camera)
this.cache;     //  the game cache (Phaser.Cache)
this.input;     //  the global input manager. You can access this.input.keyboard, this.input.mouse, as well from it. (Phaser.Input)
this.load;      //  for preloading assets (Phaser.Loader)
this.math;      //  lots of useful common math operations (Phaser.Math)
this.sound;     //  the sound manager - add a sound, play one, set-up markers, etc (Phaser.SoundManager)
this.stage;     //  the game stage (Phaser.Stage)
this.time;      //  the clock (Phaser.Time)
this.tweens;    //  the tween manager (Phaser.TweenManager)
this.state;     //  the state manager (Phaser.StateManager)
this.world;     //  the game world (Phaser.World)
this.particles; //  the particle manager (Phaser.Particles)
this.physics;   //  the physics manager (Phaser.Physics)
this.rnd;       //  the repeatable random number generator (Phaser.RandomDataGenerator)

//  You can use any of these from any function within this State.

 

Link to comment
Share on other sites

 Share

  • Recently Browsing   0 members

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