【问题标题】:function(a,b) { a = b; } doesn't change the value of a in javascript函数(a,b) { a = b;不会改变 javascript 中 a 的值
【发布时间】:2014-08-20 03:27:43
【问题描述】:

我写了如下代码:

function setAtoB(a, b) {
    console.log('entered function');
    a = b;
}
var x = {};
var y = {'t':3};
setAtoB(x, y);
console.log(x);

然后我得到这样的输出:

entered function
{}

在我看来 x 应该是 {'t':3}。有谁知道为什么它仍然是 {},以及如何在函数中分配值?

【问题讨论】:

标签: javascript function reference arguments variable-assignment


【解决方案1】:

在 setAtoB 函数中,您将 a 替换为 b,这会破坏 a 对调用堆栈中更高一级调用者的引用。将对象传递给函数时,您可以在不破坏该链接的情况下替换它们的属性,但是当您执行任何类型的重新分配时,该链接会中断并创建一个新对象。

例如,如果您只替换属性,则保留引用:

function setAtoB(a, b) {
    console.log('entered function');
    a.t = b.t;
}
var x = {};
var y = {'t':3};
setAtoB(x, y);
console.log(x);    // output: Object {t: 3} 

【讨论】:

  • 引用不被保留,在调用setAtoB 之后,像x.t=20 y 的t 属性将不等于20
  • @PatrickEvans - 不确定我是否遵循。似乎将 x.t 更改为 20 会导致打印 20:jsfiddle.net/HaS5b
  • 啊,我明白你在说什么,是的,当你将属性从一个对象复制到另一个对象时,你正在制作这些属性的实际副本,这可能是也可能不是你想要的.但在这种情况下,这与 OP 正在寻找的结果一致。
  • +1 总体而言,虽然 "...a 对调用堆栈中更高一级调用者的引用" 似乎令人困惑或具有误导性。没有对调用者的引用,并且这个问题与调用堆栈没有任何关系,除非我完全错过了你在那儿所说的内容。有问题的引用是对象本身,它由x 持有并复制到a,然后由y 持有并复制到b 替换。
  • 我明白了。我倾向于更多地从盒装指针的角度来考虑它,其中指针取消引用受到盒子的限制和控制,指针指向存在于内存中某个未知位置的实际对象,并且盒子对象被传递/分配按值(复制)。所以要使用一些伪语法var foo = [0x1030e0d8] -> [b1="bar", b2="baz"].
【解决方案2】:

JavaScript 总是按值传递,所以你不能直接做你描述的事情。当对对象的引用传递给函数时,您可以修改对象的属性,但不能更改调用环境中使用的原始变量。换句话说,在调用中:

setAtoB(x, y);

它是传递给函数的变量“x”值的副本。变量 "x" 的值是对对象的引用,因此传递的是该引用的 copy。该引用的工作原理与“x”中仍然存在的副本一样可以更改引用的对象,但是更改包含副本的参数对“x”的值没有影响。

【讨论】:

  • “对象引用是按值传递的”是有人在写 Java 时曾经说过的话。也许这个人:javadude.com/articles/passbyvalue.htm 但我不记得是谁第一次写的。我在这里也用 JavaScript 介绍了相同的概念:blog.opensourceopportunities.com/2008/07/…。虽然这些语言的新手有些困惑,但您所写的实际上是正确的。 “JavaScript 总是按值传递...”。
  • @jmort253 是的,这非常令人困惑。问题是术语“按值传递”和“按引用传递”具有特定的技术含义,但对于不是编译器/解释器实现者的人来说,它有点神秘。这个问题实际上触及了问题的核心!另见a blog post I did
猜你喜欢
  • 2014-03-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-06
  • 2021-11-28
  • 2019-01-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多