3

I need a global variable "window.myHub" to set which is passed on as parameter to a function(SignalRSetUp) as below: The way it is passed on right now, doesn't set it ! How could this be resolved ?

var args = {
            "userObjectId": UserObjectId,
            "hubURL": LCSHubApiURL,
            "hubName": HubProxyName,
        }
  var callBackFuncs = {
            "ping": PingFunc
        }
window.myHub;
var signalRSetUp = new SignalRSetUp(args,callBackFuncs, window.myHub);

SignalRSetUp(argObj,eventFuncs,globalVar)
{
     var $self = this;
        var connection = $.hubConnection(argObj.hubURL);
        var hub = connection.createHubProxy(argObj.hubName);
        hub.connection.qs = { "objectid": argObj.userObjectId };

        //Wire : Call back functions and the Hub events
        for (var e in eventFuncs) {
            hub.on(e, eventFuncs[e]);
            //hub event fail
        }

        connection.start()
            .done(function () {
                globalVar = hub;
            })
            .fail(function (error) {
                console.log('Could not Connect!');
            });
}
user2837167
  • 221
  • 1
  • 5
  • 15
  • 2
    *Window.myHub* has the value *undefined*, so that is the value you are passing to *SignalRSetUp* and is assigned to *globalVar*. You can't pass a reference to a variable, you can only pass its value (noting that when you assign an object to a variable, the value assigned is a reference to the object). – RobG Jun 12 '15 at 06:50
  • please set window.myHub = {}; and then see the the result – Mudaser Ali Jun 12 '15 at 06:53
  • Why would you do this at all? Why can't you simply `return hub` from that function? – Bergi Jun 12 '15 at 06:54
  • @Bergi Also it's a constructor, you can't return things from them. – Lexi Jun 12 '15 at 06:56
  • possible duplicate of [Does JavaScript pass by reference?](http://stackoverflow.com/questions/13104494/does-javascript-pass-by-reference) – Jonathan Jun 12 '15 at 07:00
  • @LexR—you can return any object you want from a constructor. The default is to return *this*, but it's not restricted to that. – RobG Jun 12 '15 at 07:03
  • @RobG what you're saying is actually the definition of passing by reference: you pass by value the object referred by the variable. The variable is merely an "alias" to that object. About primitive types, it's just immutable objects, which make them behave a bit differently, but they're actually not! – zmo Jun 12 '15 at 07:17
  • @Rouby good one, I couldn't find better than "copy by reference" :-) – zmo Jun 12 '15 at 07:19
  • @zmo—cool, that's exactly what I wanted to say. – RobG Jun 12 '15 at 08:20
  • @LexR: Well if it's a promise you don't want to assign it to a global variable anyway. Just store the promise on the instance and assign the instance to a variable. – Bergi Jun 12 '15 at 12:30

4 Answers4

4

Javascript always work with pass by value. And when you give window.myHub as parameter to the function, you actually get a reference to the object (value) in memory referred by window.myHub.

But what's not working in your code, is that you're reassigning the referenced object in memory pointed by globalVar:

globalVar = hub;

which then has globalVar referring to whatever is in hub. i.e.: you're not changing the value of the referred value, you're changing what it points to.

If you do:

var signalRSetUp = new SignalRSetUp(args,callBackFuncs, window);

and then in your code:

SignalRSetUp(argObj,eventFuncs,aWindow) {
    //...
    aWindow.myHub = hub;
    //...
}

then you'll be replacing the referenced value of the member myHub within the object aWindow.

Considering that window.myHub is containing undefined, then what you actually do is passing undefined as globalVar, and then changing where globalVar points to:

here's your variables when you start:

memory: [xxxxxxxxxxx]
              ^
              |
         window.myHub

Then you call the function SingalRSetUp:

          globalVar
              |
              v
memory: [xxxxxxxxxxx]
              ^
              |
         window.myHub

Then you assign something else to globalVar:

                     globalVar
                         |
                         v
memory: [xxxxxxxxxxx|yyyyyyyyyyy]
              ^
              |
         window.myHub

When I suggest that you pass any sort of mutable object (whether this is an array, or an object), then you can use the fact that you're referencing this object throughout your program, and it will be responsible to be some sort of "registry" (maybe can we find a better word for that) of the right references:

          aWindow     aWindow.myHub
              |          |
              v          v
memory: [xxxxxxxxxxx|yyyyyyyyyyy]
              ^          ^
              |          |
            window    window.myHub

That said, the whole purpose of a global variable — such as window — is that it can be accessed from any place in the program, and you could simply avoid to pass it as a parameter, as @NLN suggests, you can simply access it from within the function.

zmo
  • 24,463
  • 4
  • 54
  • 90
  • The SignalRSetup() is a generic method, so anyone could use it provided you pass the intended parameters to it. So it would not know which caller wants which global variable to be set. Hence we would want to send specifically as parameter. – user2837167 Jun 12 '15 at 16:28
  • "Javascript always work with pass by reference" Wrong. JavaScript is ALWAYS pass-by-value, just like Java. There is no pass-by-reference in JavaScript. What you described is exactly what "pass-by-value" means. – newacct Jun 15 '15 at 19:13
  • good point and mea culpa and edited answer. Javascript is indeed pass by value, and every variable is a reference. When you pass the referred value as an argument, you get a new reference of that value within the scope of the function. My bad, I guess I wrote the answer too early for my brain to be fully functional :-) – zmo Jun 15 '15 at 19:58
2

window.myHub is being passed as undefined to SignalRSetUp() since you havnt initialized it before passing.

window.myHub = "default value";

More importantly, since myHub is global to window scope, you dont need to pass it in the function. It'll be available in SignalRSetUp() straightaway.

Cheers!

nalinc
  • 7,375
  • 24
  • 33
2

You are passing by value when sending in window.myHub. Send in the parameter as "window" if you want to have pass by reference.

For e.g.

SignalRSetup(argObj,eventFuncs,globalVar) {
       .....
       globalVar.myHub = hub
}

var signalRSetUp = new SignalRSetUp(args,callBackFuncs, window);
// Now window.myHub will have the value from the method

A good reference is here

rajasaur
  • 5,340
  • 2
  • 27
  • 22
  • well, technically what you say is right, but even though it *looks* like pass by value, the article you're referring to is wrong. Javascript *always* pass by reference any variable. It's just that primitive types variables are immutable. When you do an assignment, you're not changing the referenced object, you're replacing what the variable is referring, effectively deallocating the original object, replacing it with the new one. Because the object referred to was what was shared between caller and callee, once you loose it, you loose your "link" with the caller. – zmo Jun 12 '15 at 07:10
  • @zmo: NO, JavaScript is ALWAYS pass-by-value. Always. Just like Java. There is no pass by reference in JavaScript. What you described is exactly what "pass-by-value" means. – newacct Jun 15 '15 at 19:12
  • damn, I'm not gonna delete that comment, but re-reading it shows me how wrong I was. Thanks for your correction, and mea culpa! ;-) – zmo Jun 15 '15 at 19:58
1

You can do it by passing the name of the variable, then accessing it as a property of the global object, so:

// Create global
var myHub;
var globalObj = this;

// Pass property name as a string and object to resolve it on 
// as a reference
var signalRSetUp = new SignalRSetUp(args,callBackFuncs, 'myHub', globalObj);

// Resolve in callback
function SignalRSetUp(argObj, eventFuncs, globalVarName, globalVarObj)
{
    ...
            .done(function () {
                globalVarObj[globalVarName] = hub;
            })
    ...
}

You could not pass the global object and just assume it's the same one (probably extremely likely but if you use frames might be required) but you might want to change it to some other object to avoid the global, in which case you might just pass the object around and maybe also give it a method to get and set the property.

RobG
  • 142,382
  • 31
  • 172
  • 209