[JS] Accessing an object's property in a nested function?

Hello guys, I am want to make key binding work. I would like to make the paddle_y_pos property accessible from within the function keyDown(), which is nested within a different function, called update(), which updates the animation frames. Can you expain to me how I can accomplish this? Thank you!

paddle_y_pos is accessible as long as the Paddle instance you’re referencing it from is accessible. The only Paddle instance I see you using is paddleLeft, but I’m not seeing that defined (or declared) anywhere prior. You define it in keyDown, but after you access paddle_y_pos which will fail because it doesn’t yet exist.

I’m not seing anything dynamic in the Paddle instance created there; the input values are all constant. So I’m assuming what you really want is for it to be defined in your script scope? For example, above update:

// moved out of keyDown:
var paddleLeft = new Paddle(20, HEIGHT / 2 - 25, PADDLE_WIDTH, PADDLE_HEIGHT);

function update() { ...

This way, paddleLeft will be defined when keyDown gets called.

And I assume you have HEIGHT, PADDLE_WIDTH, and PADDLE_HEIGHT defined somewhere else too? I don’t see them but assume you’re distinguishing their difference between Paddle.PADDLE_WIDTH and Paddle.PADDLE_HEIGHT.

One more thing: update should really be:

function update() {
   paddleLeft.draw();
}

Take everything else out of it. You don’t need to set up key listeners every time you update - with a new function on top of that. You’re leaking listeners like crazy doing this. All you want to do is set up key listeners once on init, have data updated in those listeners when those events occur (paddleLeft.paddle_y_pos -= paddleLeft.paddle_y_pos;) and then your screen can get redrawn in an update based on anything that might have changed since the last time it happened.

If you want to take it a step further, you can ditch setInterval and use the recommended requestAnimationFrame instead

Going beyond that you can prevent updates unless something has changed (validation). But thats an optimization I wouldn’t worry about just yet :wink:

Thanks for the useful tips. I moved the functions defining the keyb controls outside the update() function. Now the console outputs ReferenceError: Can't find variable: ball.

I don’t get it: I declare and assign a variable ball to the new instance of the Ball object. This variable should be accessible everywhere in the code. But I receive the error I mentioned above…

ball (and a bunch of others) are defined with var in a function. When you use var in a function, it makes a variable that’s local to that function and (typically) only lasts until that function has completed executing.

// ball doesn't exist
draw(); // ball exists in the block of this function while its called...
// ball doesn't exist
draw(); // a new ball is created and lasts for only this function call...
// no balls

If you want ball to be accessible anywhere, then you need to define it outside of a function, as I suggested with paddleLeft.

This is clear now, thank you. I made quite a few changes to the code and I would like to know what you think about them:

  • Moved most of the vars inside the function init() and attached them
    to the Window object to make them public.
  • Added the requestAnimationFrame() call (with a callback to the function
    draw()) to the anonymous function window.onload. I am also
    calling it recursively within the draw() function, as I found suggested elsewhere.
  • Moved the ball collision detection into a Ball.collide() method.
  • Moved the ball vector incrementer into the Ball.draw() method.

Bottom line, the code stopped working, but I am using all this situation as a learning tool, since I am pretty new to this level of programming complexity. Thank you for helping me learn. :smile:

Using window works, but not recommended. In HTML (JavaScript in HTML), window is considered global. And most of the time - with good reason - you’ll hear people warn against making global variables where possible. The fewer you have, the better. This helps keep the global space clean reducing collisions; something important if you ever need to decide to include any 3rd party code.

For example, did you know that in the chrome console there’s already a window.keys function defined?

Your keys variable would replace this preventing you from being able to use the original if you ever wanted to.

That being said, if you were to define vars outside of any functions in this context, they would actually be defined in window. So what’s the difference? With this set up, there isn’t much one. But, using var outside of a function is less typing. :wink: It also makes your code more portable since you’re not explicitly targeting an external object for variables to be defined. What if window didn’t exist? Everything would break! (Node.js, for example, has no window and instead uses an object called global for a global namespace). Similarly, and I wouldn’t worry about this too much right now, its been an increasingly more popular pattern to define applications in a single, self-contained, self-executing function (a.k.a. an IIFE, or Immediately Invoked Function Expression). That looks something like…

(function(){ // <- IIFE

   var myThis = 1;
   var myThat = "2";
   function thisOrThat (value) {
      return value === this ? "this" : "that";
   }

})(); // <- IIFE getting called just as its defined

Again, I wouldn’t worry about this too much right now, but you might see it appear now and then. The point is, using var instead of window means if you wrapped your entire code in one of these, it would still work, even without window.

But I digress. This window stuff is not likely related to your problems.

It seems to me your problem is the fact that you’re changing these ball_vel_x/y_pos variables which are defined in window but only used when creating your ball instance. Being globally defined, its fine (good) to have them as init values, though more likely they would be defined in the CONSTANT style. Then the ball is created with those start values and changes to those values would be handled through the ball instance, e.g. ball.ball_center_x_pos = upper_left[0]; I think you just need to make sure you’re using the right variables there.

P.S. Good job with requestAnimationFrame!

Thanks for your great insights. I have one more question before going on with the development: my animation shows all the frames that have been painted on the canvas. Is there a built-in function to clear the previously drawn frame? Also, which online JS reference docs you suggest me to keep at hand during the development?

clearRect. To clear the whole thing: CANVAS.clearRect(0, 0, WIDTH, HEIGHT)

Thanks, I placed it in the draw() function, before the requestAnimationFrame() call, but I am not sure it is correct. I assume you first want to clear the canvas and then request the new frame…

Can you also suggest me one online JS reference doc to keep at hand during development?

You want to clear the canvas as the first step of drawing a frame. This would mean before any other draw calls. People see the results of a frame after the requestAnimationFrame has completed. So everything you do up to that point is what the user sees. Clearing at the end of that step (since draw is called in a requestAnimationFrame()) would mean the user sees nothing.

requestAnimationFrame(fn) is more of a setFunctionToCallDirectlyBeforeNextFrameRefresh(fn). What makes it a little tricky is that if you want to keep doing things before each frame, you have to call it again every time your before-frame-refresh function (draw) is called (which then applies to the next frame).

As for references go, Mozilla is pretty good (the fist link I posted in this thread is their documentation). They’re the boy scouts of HTML/JS and have decent docs, though not without its holes. Anything else you can usually google. If you want to get specific, theres also the specs for the features themselves, but thats usually overkill. Good if you really want to understand the intent and whats really going on.
http://www.w3.org/TR/animation-timing/#dom-windowanimationtiming-requestanimationframe

The Mozilla docs often references these too (though not always correctly, the example above being one those - right page, wrong anchor)

Got it. Thank you. I found the “anatomy of a videogame” article pretty interesting, and it also touches on what you said about requestAnimationFrame(callback).

I am trying to make the code more correct by nesting the properties in sub properties, but the first line of this code returns a SyntaxError: Unexpected token '.'. Expected a ')' or a ',' after a parameter declaration. How do you correctly write function arguments nested in a sub object initializer or function?

function PitchLine(from.x, from.y, to.x, to.y) {
    this.from = {
        x: null,
        y: null
    };
    this.to = {
        x: null
        y: null
    };
}

Thank you )

Arguments are identifiers. What that means is that the comma-separated list between function PitchLine{ and ){ can’t be more complex than the syntax you can use for variables names. (Not withstanding ... rest parameters in ES6, or what not). So $fromX is okay, fromX is okay, from_X is okay, but from.x is invalid, from[x] is invalid, from{x} is invalid, and { from: x } is invalid.

In general, you shouldn’t be thinking about properties and subproperties in argument lists. There’s a really significant difference between variables and properties. Variables correspond more closely to identifiers, which are the things which correspond to names you give to things which can’t be easily changed after you write the program.

I can imagine a function like this:

function PitchLine(from, to){
    from.x = null, from.y = null,
    to.x = null, to.x = null
}

You seem to be inventing terminology as you go along, which is fine, but the terms you invent don’t necessarily exist in a language someone else created (ex: JavaScript). For instance, a “sub object initializer” isn’t a particularly concrete term; you might know what you mean by it, but it’s only half helpful to people who know a lot about extant JS terms. It’s typically more useful to describe what you want to happen using less technical terminology, rather than inventing it on your own without any sort of consensus.


I realize it’s probably frustrating that I’m criticizing the syntax you’ve invented, but it’s pretty difficult to infer meaning from something when you only have a single example. Imagine trying to learn Quenya from LotR with only 1 or 2 words as an example, rather than a grammar. And it’s understandable that you don’t know what should and shouldn’t work in JS, but it’s hard to know what you mean when you express problems you’ve encountered as making things ‘more correct’, when it’s unclear what you’re using as a basis for correctness.

Thanks for your insights.

Terminology-wise, isn’t the following called object initializer (also called object literal)?

MyObject = {
}

therefore I thought the following (in the context of my code) to be a nested object initializer/literal, or sub object initializer/literal:

this.from = {
    x: null,
    y: null
};

And I thought this is a property:

x: “some-value”

and this is a variable:

x = “some-value”

Terminology aside, the big thing here is that function parameters must be simple variables. They cannot be complex, as seen with all of krilnon’s examples.

Object initializers/literals can be used in a function body as you have, but you have to manually make the connections between the parameter list and those variables

function PitchLine(from_x, from_y, to_x, to_y) { // no dots, just variables
    this.from = {
        x: from_x, // from from_x argument value to this.from.x value
        y: from_y
    };
    this.to = {
        x: to_x
        y: to_y
    };
}

To add to this, I wouldn’t say this makes your code “more correct”. In fact theres a law or something that talks about how you should limit the number of references you make through objects to get to a certain value. In fact I think its suggested that it should never go beyond 1? I can’t remember who said this or how it goes, but the gist it basically: This.isGood; This.is.not.good; Obviously different circumstances favor having deeper referencing so its not something you can be too religious about, but I think a takeaway is this: keep things simple. Limit what you can do with objects and have them abstract away as much of their implementation as possible so working with them is easy and concise.

Additionally, getting back to the intialization/parameter thing, if you ever decide to get into something like CoffeeScript, you can set up your parameters with names that automatically set variables of the same name in this when the function (as method or constructor) gets called. Go over to http://coffeescript.org/ , hit the Try CoffeeScript tab and throw this in there:

class PitchLine
   constructor: (@fromX, @fromY, @toX, @toY) ->

Simple! It would be more complex if you needed to cram those values into other objects defined in the constructor

Tell that to the graphics API people.

To me it sounds like a rule mostly coming from people talking about too many chained references messing up memory locality. Rather than something that necessarily influences code comprehension by humans. :shrug:

Found it