Using a JavaScript Function as a Class

Click For Summary

Discussion Overview

The discussion revolves around the implementation of a JavaScript function intended to act as a class for creating a "snake" object in a graphical context. Participants explore issues related to the function's behavior, particularly how to maintain the correct context for method calls within the function.

Discussion Character

  • Technical explanation
  • Exploratory
  • Debate/contested

Main Points Raised

  • One participant identifies a bug related to the context of the `move` method, noting that it incorrectly refers to a nonexistent member `body` instead of the outer function's member.
  • Another participant suggests using `Function.prototype.bind` to remedy the context issue when calling `setInterval` with the `move` method.
  • A follow-up question arises about alternative methods to achieve the same result without using `bind`.
  • A proposed solution involves creating a custom `bind` function and using a closure to maintain the context by storing a reference to `this` in a variable (e.g., `that`).

Areas of Agreement / Disagreement

Participants generally agree on the context issue and the utility of `bind`, but there is no consensus on the best approach without using `bind`, as multiple alternatives are discussed.

Contextual Notes

Participants discuss the limitations of the current implementation, particularly regarding the handling of context in JavaScript functions and the implications of using `setInterval` with method references.

Jamin2112
Messages
973
Reaction score
12
I figured out what the bug in my code is, but now I need to figure out how to best remedy it.

Here's my function:

Code:
        function snake(C, C_h, C_w)
        {
                /* NOTE TO SELF: C is a Raphel object. Can't find a method to return the height
                   and width of a Raphael object in the documentation: 
                   [PLAIN]http://raphaeljs.com/reference.html#Raphael.[/PLAIN] 
                   Using C_h and C_w for now, but should probably change it later.
                */
            
                this.linkSize = 10; // size of a snake unit, in pixels
                
                /* On instantiation, the snake direction is down and has 1 link */
                this.dy = this.linkSize;
                this.dx = 0;
                this.link = C.rect(C_h/2, C_w/2, this.linkSize, this.linkSize);
                this.link.attr("fill", "#d7a900");
                this.body = [this.link];
                
                /* Event listener for changing the direction of the
                   snake with arroy keys on the keyboard
                */
                this.redirect = function(dirnum)
                {
                    switch (dirnum)
                    {
                        /*
                            dirnum corresponds to
                            1 ---> right
                            2 ---> down
                            3 ---> left
                            4 ---> up
                        */
                        case 1: 
                            this.dx = this.linkSize;
                            this.dy = 0;
                            break;
                        
                        case 2:
                            this.dx = 0;
                            this.dy = this.linkSize;
                            break;
                        
                        case 3:
                            this.dx = -this.linkSize;
                            this.dy = 0;
                            break;
                        
                        case 4:
                            this.dx = -this.linkSize;
                            this.dy = 0;
                            break;
                        
                        default: // never happens
                            break;
                    }
                            
                }
[B]                this.move = function()
                {
                    /*
                        ...
                    */
                    
                    var temp = this.body[0];
                    this.body[0].translate(this.dx, this.dy);
                    for (var i = 1, j = this.body.length; i < j; ++i)
                    {
                        this.body[i] = temp;
                        temp = this.body[i];
                    }
                }[/B]
                this.mover = setInterval(this.move, 500);                

        }

The problem is in the bolded block. I want to refer to the outer function's member body, but I realize it's instead referring to move's nonexistent member body. What is the best way to remedy this?
 
Last edited by a moderator:
Technology news on Phys.org
Newer browsers have Function.prototype.bind

setInterval( this.move.bind(this), 500 );
 
DavidSnider said:
Newer browsers have Function.prototype.bind

setInterval( this.move.bind(this), 500 );

That's useful. Out of curiosity, how would I have done it without this feature?
 
Jamin2112 said:
That's useful. Out of curiosity, how would I have done it without this feature?

The implementation looks something like this
Code:
Function.prototype.bind = function (scope) {
    var fn = this;
    return function () {
        return fn.apply(scope);
    };
}

This would have worked too

Code:
    var that = this;
    setInterval(function() {
        that.move();
    }, 500);
 
Last edited:

Similar threads

  • · Replies 5 ·
Replies
5
Views
3K
  • · Replies 2 ·
Replies
2
Views
2K