在JavaScript中通过引用传递变量

387

如何在JavaScript中通过引用传递变量?

我有三个变量,想对它们执行一些操作,因此希望将它们放入for循环中,并对每个变量执行操作。

伪代码:

myArray = new Array(var1, var2, var3);
for (var x = 0; x < myArray.length; x++){
    // Do stuff to the array
    makePretty(myArray[x]);
}
// Now do stuff to the updated variables

什么是最佳的做法?


37
你提到了“按引用传递”,但在你的例子中并没有函数调用,因此在你的例子中根本没有传递。请澄清你想要做什么。 - jfriend00
1
抱歉让您感到困惑。我并不需要特别编写一个函数,所以“传递引用”是一个不太恰当的措辞。我只是想对变量执行一些操作而无需编写:makePretty(var1); makePretty(var2); makePretty(var3); ... - BFTrick
1
根据您的评论:arr = [var1, var2, var3]; for (var i = 0, len = arr.length; i < len; i++) { arr[i] = makePretty(arr[i]); } -- 您只需要将 makePretty 返回的值存储回数组中的槽位即可。 - dylnmc
1
对于那些在谷歌搜索“Javascript中的按引用传递”或“按值传递”的人,这篇来自Medium的好文章是:https://medium.com/@TK_CodeBear/javascript-arrays-pass-by-value-and-thinking-about-memory-fffb7b0bf43 - Erenor Paz
1
@ErenorPaz。Medium的文章已经成为了死鹦鹉的命运! - Patanjali
谢谢@Patanjali(喜欢你的比喻),我想建议一些更加“实在”的东西(希望如此,考虑到互联网资源非常不稳定(就像一只鹦鹉,我们可以这么说)),来自Geeks4geeks:https://www.geeksforgeeks.org/pass-by-value-and-pass-by-reference-in-javascript/。但是,我相信现在已经有很多参考资料了,Google比这个评论更能帮助我们 :-) :-) - Erenor Paz
17个回答

2
由于我们没有JavaScript传递引用的功能,唯一的方法是使函数返回值并让调用者分配它:
因此
"makePretty(myArray[x]);"

应该是

"myArray[x] = makePretty(myArray[x]);"

如果需要在函数内部进行赋值,那么传递对象并对其进行变异应该足够了;否则,只需要变异。


这通常也是一个更好的设计,除非它存在可证明的性能问题:功能性、无状态的设计会产生较少的复杂性。如果调用者想要使用结果来改变某些东西,那是他们的决定,但函数没有权力强制这样做。 - undefined

1

不考虑引用传递的讨论,仍在寻找解决所述问题的人可以使用以下方法:

const myArray = new Array(var1, var2, var3);
myArray.forEach(var => var = makePretty(var));

3
什么是解释?它与其他答案有何不同/更好之处? - Peter Mortensen

0

在这里使用解构,以下是一个例子,我有3个变量,在每个变量上执行多个操作:

  • 如果值小于0,则更改为0,
  • 如果大于255,则更改为1,
  • 否则将数字除以255以从0-255的范围转换为0-1的范围。
let a = 52.4, b = -25.1, c = 534.5;
[a, b, c] = [a, b, c].map(n => n < 0 ? 0 : n > 255 ? 1 : n / 255);
console.log(a, b, c); // 0.20549019607843136 0 1

0

我明白你的意思。在 Swift 中,同样的事情不会有问题。关键是使用 let,而不是 var

基本类型被按值传递,但是在迭代时 var i 的值并没有复制到匿名函数中,这一点令人惊讶至少可以这么说。

for (let i = 0; i < boxArray.length; i++) {
  boxArray[i].onclick = function() { console.log(i) }; // Correctly prints the index
}

0
这可能不能完全回答所提出的问题,但对于许多涉及该主题的情况来说,更具功能性的设计是一条富有成果的途径,它实际上减少了复杂性,而不是增加了复杂性。
result = new Array(var1, var2, var3)
    .map(makePretty)

我保留了问题中的命名,但遵循“动词用于副作用”的原则,应用的转换更好地命名为“pretty”。 - undefined

0

我喜欢解决 JavaScript 中缺乏“按引用传递”的问题,就像这个例子所展示的那样。

它的本质是不要试图创建一个“按引用传递”。相反,您可以使用返回功能,并使其能够返回多个值。因此,没有必要将您的值插入数组或对象中。

var x = "First";
var y = "Second";
var z = "Third";

log('Before call:',x,y,z);
with (myFunc(x, y, z)) {x = a; y = b; z = c;} // <-- Way to call it
log('After call :',x,y,z);


function myFunc(a, b, c) {
  a = "Changed first parameter";
  b = "Changed second parameter";
  c = "Changed third parameter";
  return {a:a, b:b, c:c}; // <-- Return multiple values
}

function log(txt,p1,p2,p3) {
  document.getElementById('msg').innerHTML += txt + '<br>' + p1 + '<br>' + p2 + '<br>' + p3 + '<br><br>'
}
<div id='msg'></div>


这种方法需要大量的标识符和赋值来解决基本问题,但它并没有解决那些需要明确引用才能解决问题的情况。一些例子包括在引用上创建新属性或删除属性,在许多函数之间传递引用,更改类型或完全替换引用等。因此,在JS世界中,解决这个问题的理想解决方案将涉及使用Flyweight模式和某种对象的变体。 - Andrew
这种方法在这里有所讨论。此外,在JS对象中传递变量时,不需要做 { a: a, b: b, c: c } 等操作,可以直接使用 { a, b, c }。最后,您可以在函数调用行上使用Destructuring Assignment,无需使用 with。(如果您确实使用了 with,则建议仅使用作用域括号 {}。) - Andrew

0
如果您想通过引用传递变量,更好的方法是通过将参数传递到对象中,然后使用window开始更改值:
window["varName"] = value;

例子:

// Variables with first values
var x = 1, b = 0, f = 15;


function asByReference (
    argumentHasVars = {},   // Passing variables in object
    newValues = [])         // Pass new values in array
{
    let VarsNames = [];

    // Getting variables names one by one
    for(let name in argumentHasVars)
        VarsNames.push(name);

    // Accessing variables by using window one by one
    for(let i = 0; i < VarsNames.length; i += 1)
        window[VarsNames[i]] = newValues[i]; // Set new value
}

console.log(x, b, f); // Output with first values

asByReference({x, b, f}, [5, 5, 5]); // Passing as by reference

console.log(x, b, f); // Output after changing values

1
但是在Web浏览器上下文中,window是全局(别名?)对象(?)。因此,在全局变量中有效地传递信息(?)。 - Peter Mortensen
1
@PeterMortensen 这就是为什么我喜欢建议只需手动分配/重新分配内联变量的答案,不论在什么上下文中使用。但是,如果有人想要,他们也可以传递他们想要变量存在的上下文/命名空间/对象,globalThis是默认值(避免了仅限Web浏览器的问题),尽管这种方法不幸需要将变量名作为字符串传递。 - Andrew

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