将全局变量传递给函数

20

为什么下面的代码会给我一个0而不是1?我想让我的函数改变在函数外声明的一个变量,但我不想在函数声明中指定变量。

that = 0;

function go(input) {
    input++;
}

go(that);

console.log(that);

1
离题:始终使用“var”声明变量。或者,如果它是全局变量,您也可以将它们设置为“window”的属性(例如,“window.that = 0”)。 - Oriol
5个回答

22

正如Oriol所回答的那样,它不起作用是因为变量是按值传递的,因此您没有改变“that”变量。一个解决方法是通过变量名称进行传递:

that = 0;

function test(input) {
    window[input]++;
}

test("that");

console.log(that); // 1

我正在寻找一种方法来使用window.input,而不是指外部声明的变量input。 - Emanegux
1
我认为这是你能做到的最接近的方式。测试函数没有引用任何变量,它只是从参数中获取变量。你的问题说“我不想指定变量”。否则,你将不得不像其他人在他们的答案中描述的那样使用一个对象。 - Phil-R

20

那是因为你正在按值传递变量,而不是按引用传递。

在 JavaScript 中,所有变量都是按值传递的,除了对象,它们是按引用传递的(实际上它们也是按值传递的,但它们是引用类型,请参见下面)。

而且你不能改变这种行为。

编辑:如果你不知道什么是按值/引用传递,你应该阅读一份教程。但是这里有一些例子:

  • 按值传递的变量

function foo(bar){
   console.log(bar); // 1
   bar++;
   console.log(bar); // 2
}
var mybar = 1;
console.log(mybar); // 1
foo(mybar);
console.log(mybar); // 1
  • 以值传递方式传递但用作引用的变量

  • function foo(bar){
       console.log(bar.a); // 'b'
       bar.a = 'c';
       console.log(bar.a); // 'c'
    }
    var mybar = {a:'b'};
    console.log(mybar.a); // 'b'
    foo(mybar);
    console.log(mybar.a); // 'c'
    

    在您的情况下

    您可以将变量作为对象的属性(在这种情况下,由于它是全局变量,请使用window),并传递该对象(引用),以便您可以更改它。

    window.that = 0;
    function go(obj) {
        obj.that++;
    }
    go(window);
    console.log(that); // 1
    
  • 使用返回值

  • var that = 0;
    function go(input) {
        return input++;
    }
    that = go(that);
    console.log(that); // 1
    

    请注意,您无法执行以下操作:

    • 将您的变量转换成对象

    var that = new Number(0); // Now it's an object number
    function go(input) {
        input++;
    }
    go(that);
    that *= 1; // Now it's a literal number
    console.log(that); // 0
    

    这是因为对象也是按值传递的,但它们是引用。这意味着在函数内部,您可以更改外部对象的属性(因为它是一个引用),但无法更改整个对象,因为它是按值传递的。

    在此处查看示例:https://dev59.com/5nRB5IYBdhLWcg3wxZ7Y#3638034


    你能详细描述一下你的意思吗? - dezman
    这里有一个很好的教程,在snook.ca上 - Andy G

    3
    这与指针、作用域、通过引用传递变量等有关。
    如果你真的想要这样做,在Javascript中可以像这样传递一个对象:
    var that = {value: 0};
    function go(input) {
        input.value++;
    }
    go(that);
    console.log(that.value);
    

    我们所做的只是将“那个”作为一个对象,在JavaScript中,按照定义传递引用。然后我们只需确保正确地修改对象的属性。


    1

    您的代码

    that = 0; //全局变量
    function go(input) { //input是参数,不是通过引用传递的 input++; //这只是增加了一个本地副本即0 }
    go(that); //传递了0
    console.log(that);

    改成这样

    that = 0;
    function go() { that++; }
    go(); //没有传递任何变量..函数已经能看到全局"that"
    console.log(that); //这将打印全局即1

    我不确定是否理解。如果变量未被声明,输入++将如何更改变量? - Emanegux

    -4
    实际上您可以在函数内部添加console.log(input),这样就可以正常工作了。
    如果我错了,请纠正我。希望我已经帮到您了!!
    如果有人能解释我为什么错了,我会很高兴的。

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