user1960364
user1960364

Reputation: 2001

JavaScript variable scopes

I'm trying to build a simple application where I'll be creating multiple instances of a Box object which will control and manipulate its own data. However, I'm having trouble figuring out how to create global variables for use within each individual object and it's associated prototypes...

For example, I tried to make a reference to itself...

function Box( boxData ) {
    // References the Box instance as I want.
    console.log( this );

    // I need to access this later...
    var boxName = boxData.name;

    var canvas = $( '#rm-' + boxData.id ).find( 'canvas' )[0];
    $( canvas ).on( 'mousedown', this.onMouseDownHandler );
}

Box.prototype.onMouseClickHandler = function( event ) {
    // 'boxName' is undefined as 'this' references 'event.target'
    console.log( this.boxName );
}

Keep in mind that it can't act as a singleton as I'll have multiple instances of it at any one point in time.

Edit:

I'm adding the event listener in the constructor with, updated the above code.

Upvotes: 2

Views: 81

Answers (3)

Gabriel Gartz
Gabriel Gartz

Reputation: 2870

For your canvas work with Box instance as it context, you need to bind it.

You can try something like this:

function Box( boxData ) {
    // References the Box instance as I want.
    console.log( this );

    // I need to access this later...
    var boxName = boxData.name;

    // public property boxName
    this.boxName = boxName;

    var $canvas = $( '#rm-' + boxData.id ).find( 'canvas' );
    $canvas.on( 'mousedown', this.onMouseDownHandler.bind(this) );
    // ----------------------------------------------^
    // this bind will prevent the event use canvas element as context
}

function Room() {
    // some stuff
}

Room.prototype = new Box({name: 'this will always be my rooms box'});

Room.prototype.onMouseClickHandler = function( event ) {
    // 'boxName' is undefined as 'this' references 'event.target'
    console.log( this.boxName );
}

Now you are able to try this:

var foo = new Room();
foo.onMouseClickHandler();

And your console will log this will always be my rooms box.

You keep in mind that Room extends a instance of Box, so if you do:

foo.boxName = 'my name is what?!';

// you changed the this so the prototype will get the new value:
foo.onMouseClickHandler(); // 'my name is what?!'

EDIT (after question upgrade)

Simply use this.boxName instead var boxName:

function Box( boxData ) {
    // References the Box instance as I want.
    console.log( this );

    // public property boxName
    this.boxName = boxName;
}

And if you want to add a EventHandler for other object but keep your Box context you need to do this:

var foo = newBox({boxName: 'foo'});
var bar = document.queryElementById('bar');

bar.addEventHandler('click', foo.onMouseClickHandler.bind(foo));

Now if you click in bar element, the onMouseClickHandler from foo, will keep it context. The click event will be passed throw the argument.

Upvotes: 2

Bergi
Bergi

Reputation: 664538

You've actually got two problems.

variable scopes

Variables in JS always have function scope. A local variable in the constructor function will stay local to the constructor, and cannot be used outside.

create global variables for use within each individual object

it can't act as a singleton

Global, static variables seem to be the opposite of what you want. I guess you meant public object property instead of global variable. So use one:

function Box( boxData ) {
    // References the Box instance as I want.
    console.log( this );

    // create a property to be accessed later...
    this.boxName = boxData.name;
}

'boxName' is undefined as 'this' references 'event.target'

Yes, the context of the function depends (only) on its invocation. You will need to use

 var that = this;
 ….addEventLister(…, function(event) {
      that.onMouseClick(); // "that" references the instance
 });

for registering the event.

Upvotes: 0

Konstantin Dinev
Konstantin Dinev

Reputation: 34895

You create global variables as properties of the global object (window). You can have something of the sort: window['box_instance_key']['name'] to store every instance's name.

function Box( boxData ) {
    // References the Box instance as I want.
    console.log( this );

    // I need to access this later...
    window.boxName = boxData.name;
    // or something like window[boxData.id]['boxName'] = boxData.name;
}

Room.prototype.onMouseClickHandler = function( event ) {
    // 'boxName' is undefined as 'this' references 'event.target'
    console.log( window.boxName );
}

Upvotes: 0

Related Questions