How to properly pass functions to other functions in javascript

I am trying to understand the way that javascript passes functions around and am having a bit of a problem groking why a prototype function can NOT access a var defined in a function constructor while a function defined in the constructor can access the var. Here is code that works:

   var model = function model() {
       this.state = 1;
       this.GetState =   (function(scope){
           return function(){ return scope.state;};
       })(this);
   }

    var othermodel = function othermodel(mdl) {
        this.GetStateFn = mdl.GetState;
    }

    othermodel.prototype.WriteState = function() {
        console.log(this.GetStateFn.call());
    };

    var m = new model();
    var o = new othermodel(m)


    o.WriteState();

This works and makes sense - the GetState() function can access this.state.

However, if I create GetState as follows:

 model.prototype.GetState =   (function(scope){
        return function(){ return scope.state;};
    })(this);

The result will be an error that scope is not defined.

I would prefer to have this work with the prototype method as I do not want a copy of the function in ever model, but it would seem that prototype can't work because it can't access the specific instance of the model.

So, can someone provide me with a good explanation of a) what I need to do to get this to work with prototype (assuming I can) and b) if I can't get it to work with prototype, what is the reason so I can understand better the underpinnings of the issue.

Why not simply write the function this way

model.prototype.GetState = function() { return this.state; }

var othermodel = function othermodel(mdl) {
    this.GetStateFn = mdl.GetState.bind(mdl);
}

othermodel.prototype.WriteState = function() {
    console.log(this.GetStateFn.call());
};

The above code will work, as in most cases you will execute code like m.GetState(). That is an example of invoking a function as an object method. In that case, this is guaranteed to point to the object m. You seem to know how the prototype chains work, so I won't go there.

When assigning the function reference to the other model, we use the .bind to ensure that within GetState, this points to mdl. Reference for bind: https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Function/bind

Your original IIFE's were in effect your implementation of bind. The issue was the value of this was wrong. Currently, every time you need to assign models function to some other function, you will need to use bind at all those times. You have tagged your question as node.js, bind is available on the Function prototype in node.js and any ES5 compatible browser. If you need to run the above code on older browsers or environments that do not support bind, replace bind with your IIFE.

As for why your code isn't working,

model.prototype.GetState =   (function(scope){
    return function(){ return scope.state;};
})(this);

Here, this doesn't refer to the eventual model object (m). this can refer to any one of 5 options in javascript. Refer: https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Operators/this

Lets assume the above code is in an html file inside some script tag. Then this will refer to the window object. window doesn't have any property called state, hence the undefined. If you were to console.log(this.m, this.o) at the end of you script, you would see the respective m and o objects.

When defined like this:

var model = function model() {
    this.state = 1;
    this.GetState =   (function(scope){
        return function(){ return scope.state;};
    })(this);
}

the anonymous function is declared and immediately executed. this is passed as a parameter to that self-executing function. As a result - a new function is returned, but this function has scope parameter in its closure - so that it is accessible after the scope has exited. As a result - the function, when invoked, can still access state property of that "enclosed" this (the one that became scope and was closed upon).

If you define it like this:

model.prototype.GetState =   (function(scope){
    return function(){ return scope.state;};
})(this);

the mechanism is the same, it's just this is not. It is now the context of the scope you execute the above code in. Assuming it's done in global scope - it would be window object.

If you don't want to use bind because of its support with older browsers, you could try this:

http://jsfiddle.net/j7h97/1/

var model = function (state) {
    this.state = state || new Date().getTime();
};

model.prototype.GetState = function () {
    return this.state;
};

model.prototype.WriteState = function () {
    console.log("model WriteState: " + this.GetState());
};

var othermodel = function othermodel (mdl) {
    this.GetStateFn = function () {
        return mdl.GetState.call(mdl);
    };
};

othermodel.prototype.WriteState = function () {
    console.log("othermodel WriteState: " + this.GetStateFn());
};

var model1 = new model();
model1.WriteState();
var othermodel1 = new othermodel(model1);
othermodel1.WriteState();

var model2 = new model();
model2.WriteState();
var othermodel2 = new othermodel(model2);
othermodel2.WriteState();

Seems to do what you want without bind. I created the model.prototype.WriteState for testing purposes.

It depends on where it is called. If it's in global scope, this will not refer the the model. If it's running in a browser it will refer to the global window object instead.