views:

62

answers:

3

Not sure what I'm doing wrong here, I just want to be able to have functions of an object reference the object scope

myscipt.js

function MyFoo () {
   this.name = 'myname';
}

function MyBar () {
   this.myFoo = new MyFoo();

   function setMyFoosName( name ) {
      this.myFoo.name = name;
   }
}

somepage.html

<scipt>

$('document').ready( function() {
    $.myBar = new MyBar();
}

...
some action
...

$.myBar.setMyFoosName( 'new name' );

</script>

this throws an exception:

this.myFoo.name = name; this.myFoo is not defined
A: 

this referes to the scope of setMyFoosName. You should put this in a variable, and refer to that variable:

function MyFoo () {
   this.name = 'myname';
}

function MyBar () {
   var that = this;
   this.myFoo = new MyFoo();

   this.setMyFoosName = function( name ) {
      that.myFoo.name = name;
   }
}

Try to avoid exporting variables which should remain private:

function myFoo () {
   this.name = 'myname';
}

function MyBar () {
   /* myFoo is private */
   var myFoo = new MyFoo();
   this.setMyFoosName = function( name ) {
      myFoo.name = name;
   }
}

In this way, you cannot break your function with:

$.myBar = new MyBar();
$.myBar.myFoo = new EvilObject();
$.myBar.setMyFoosName();

Of course, this depends on your use, whether myFoo should be overridable or not.

Lekensteyn
See also: Closures in JavaScript (http://robertnyman.com/2008/10/09/explaining-javascript-scope-and-closures/)
annakata
-1. That wont work. setMyFoosName will not be accessible outside of the MyBar-function.
Jakob
Although, I should point out that the general advice (putting "this" in a variable and using that one instead) is the right way to go. Take a look at my version.
Jakob
Jakob, you wre right. I still don't like the fact that `myFoo` can be modified. Looking at the purpose of `myBar` (storing a reference to `MyBar`), a better solution would making `myBar` private.
Lekensteyn
Sure, why not. That depends on what this code is going to used for and how, but I agree. It's a good idea to make things as private as possible per default (and relax it when needed), but it's not the answer to the original question.
Jakob
A: 

Cant you do an instance static method with the JSON Data type?

    var MyFoo = {
        _instance : null,

        Instance : function(){
            if(this._instance == null)
            {
                this._instance = new this.Object();
            }
            return this._instance;
        },

        Object : function()
        {
            this.name = 'not robert';
        }
    }


    function MyBar (){    
       this.setMyFoosName = function ( name ) {
          MyFoo.Instance().name = name;
       }
    }

Bar = new MyBar()
Bar.setMyFoosName('Robert');

Gives it more of a global scope and so on, aslong as MyFoo is in the global scope.

Example here.

RobertPitt
+4  A: 

Lekensteyn and Ken got it half right each.

  1. You have to put "this" in a variable, like Lekensteyn did, in order to be able to reference it inside of the nested function as well.
  2. You have to make setMyFoosName accessible outside of the scope of MyBar, by assigning it to a property of "this", like Ken did.

This is how I would do it:

function MyFoo () {
   this.name = 'myname';
}

function MyBar () {
   var that = this;
   this.myFoo = new MyFoo();

   this.setMyFoosName = function( name ) {
      that.myFoo.name = name;
   }
}
Jakob
If `myFoo` should only store a reference to `MyFoo`, it's better to make it private. See my answer.
Lekensteyn
Actually @Ken also got it right, I was about to comment in his answer but it got deleted. It all depends in how you call the `setMyFoosName` function, since it is an "instance method", you don't really need the `that` variable, because the method would be called as `myBarInstance.setMyFoosName('foo')`, and the `this` value inside the method will refer to the *base object* of the reference where it was invoked. Check [this example](http://jsbin.com/uyuti3/edit) without `that`.
CMS
CMS: Interesting observation. There's only a delicate difference (that will show up if one starts juggling with the methods), but that probably doesn't matter in practice. I'll elaborate if anyone is interested, but it will probably suffice to say that both my approach and the one deleted by Ken will work in this case. Thanks CMS!
Jakob