如何在JavaScript中通过引用传递全局变量作为参数

3
我需要一个全局变量"window.myHub"被设置,并作为参数传递给函数(SignalRSetUp),如下所示:目前的方式传递,没有设置它!应该如何解决?
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!');
            });
}

2
Window.myHub 的值为 undefined,因此这就是您传递给 SignalRSetUp 并分配给 globalVar 的值。您无法传递变量的引用,只能传递其值(请注意,当您将对象分配给变量时,分配的值是对该对象的引用)。 - RobG
请设置 window.myHub = {}; 然后查看结果。 - Mudaser Ali
你为什么要这样做呢?为什么不能直接从函数中返回 hub 呢? - Bergi
@Bergi 况且这是一个构造函数,你不能从中返回任何东西。 - Lexi
@LexR - 你可以从构造函数中返回任何对象。默认情况下会返回this,但不限于此。 - RobG
显示剩余5条评论
4个回答

4
JavaScript总是按值传递。当你将window.myHub作为参数传递给函数时,实际上你得到的是一个指向内存中由window.myHub引用的对象(值)的引用。
但是在你的代码中没有起作用的是,你正在重新分配由globalVar指向的内存中的引用对象。
globalVar = hub;

然后,globalVar 引用 hub 中的任何内容。例如:你不是在改变所引用值的值,而是在改变它指向的东西。

如果您执行以下操作:

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

然后在你的代码中:

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

那么你将替换对象 aWindow 中成员 myHub 的引用值。

考虑到 window.myHub 包含 undefined,那么实际上你正在将 undefined 作为 globalVar 传递,并且更改了 globalVar 指向的位置:

这是开始时的变量:

memory: [xxxxxxxxxxx]
              ^
              |
         window.myHub

然后你调用函数 SingalRSetUp:
          globalVar
              |
              v
memory: [xxxxxxxxxxx]
              ^
              |
         window.myHub

然后你将其他东西分配给globalVar

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

当我建议你传递任何可变对象(无论是数组还是对象)时,你可以利用你在整个程序中引用该对象的事实,并且它将负责成为某种“注册表”(也许我们可以找到更好的词)正确的引用:

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

话虽如此,全局变量——例如window的整个目的在于它可以从程序的任何地方访问,您可以像@NLN建议的那样仅通过函数内部访问它,而无需将其作为参数传递。


SignalRSetup()是一个通用方法,因此只要您向其传递预期的参数,任何人都可以使用它。因此,它不知道哪个调用者想要设置哪个全局变量。因此,我们希望将其作为参数发送。 - user2837167
"Javascript总是使用按值传递"是错误的。JavaScript始终是按值传递,就像Java一样。在JavaScript中没有按引用传递。您所描述的正是“按值传递”的含义。" - newacct
好的观点和自我批评以及修改后的答案。Javascript确实是按值传递,每个变量都是一个引用。当您将所引用的值作为参数传递时,在函数范围内获得该值的新引用。我的错,我想我写的答案太早了,我的大脑还没有完全运转 :-) - zmo

2

window.myHub在传递给SignalRSetUp()时被传递为undefined,因为您在传递之前没有初始化它。

window.myHub = "default value";

更重要的是,由于myHub是全局window作用域,您不需要在函数中传递它。它将立即在SignalRSetUp()中可用。

干杯!


2
当您发送window.myHub时,您正在通过值传递。如果要进行引用传递,请将参数设置为“window”。
例如:
SignalRSetup(argObj,eventFuncs,globalVar) {
       .....
       globalVar.myHub = hub
}

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

一份好的参考资料在这里

嗯,从技术上讲,你说的是对的,但即使它看起来像是按值传递,你所提到的文章是错误的。Javascript 总是按引用传递任何变量。只是原始类型变量是不可变的。当你进行赋值时,你并没有改变被引用的对象,而是替换了变量所指向的内容,有效地释放了原始对象,并用新对象替换了它。因为被引用的对象是调用者和被调用者之间共享的,一旦你失去了它,你就失去了与调用者的“链接”。 - zmo
@zmo:不,JavaScript始终是按值传递的。就像Java一样。在JavaScript中没有按引用传递。你所描述的正是“按值传递”的含义。 - newacct
该死,我不会删除那条评论,但重新阅读它让我意识到我是多么错误。感谢您的纠正,我承认错误!;-) - zmo

1
你可以通过传递变量名称并将其作为全局对象的属性进行访问来完成此操作,因此:
// 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;
            })
    ...
}

你不能跳过全局对象并假设它是相同的(可能极有可能,但如果使用框架可能需要),但你可能希望将其更改为其他对象以避免全局,这种情况下你可以传递该对象并可能还要给它一个获取和设置属性的方法。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接