1

我正在阅读,在 JavaScript 中,出现了一个常见的混淆点,因为基元的变量是按值传递的,而对象的变量是按引用传递的,而在函数参数中,基元和引用都是按值传递的。

在我修修补补的过程中,我编写了以下代码,但我无法理解它。

> function setName2(obj) {
... obj.name="matt";
... obj = new Object();
... obj.name="obama";
... }

如果我设置

var person = new Object();
person.name = "michelle";

然后运行

> setName2(person);

我明白了

> person.name;
'matt'

这是有道理的,因为创建的新对象是指向本地对象的指针,因此不会影响全局“人”的属性。

但是,如果我先设置

 var obj = new Object();
    obj.name = "michelle";

然后运行

  > setName2(obj);

?

我得到同样的结果。这是否意味着编译器将同名的两个变量(obj global 和 obj local)识别为对堆内不同位置的引用,每个变量都有一些不同的指针关联,还是对这种现象有不同的解释?

4

5 回答 5

2

JavaScript 没有传递引用;一切都是按值传递的。但是,有些值本身就是对对象的引用。这种区别(通过引用与 is-a-reference)导致了很多混乱。

一个清理事情的例子:

function f(o) { ... }
var obj = { foo: 42 };
f(obj);

无论你在做什么fobj总是会引用同一个对象,因为参数不是通过引用传递的。但是obj,复制到o中的 value本身就是对对象的引用。这就是为什么对函数内部所做的任何属性更改在它返回后o都将可见。obj

于 2013-09-14T11:55:06.313 回答
1

而在函数参数中,原语和引用都是按值传递的。

这不是真的。函数参数没有什么特别之处。

function setName2(obj) {

这接受对对象的引用作为参数。

obj.name="matt";

这会修改name引用指向的对象的属性。

obj = new Object();

这会将对原始对象的引用替换为对新对象的引用。

obj.name="obama";

这会修改新对象的名称属性。原始对象不变。

于 2013-09-14T11:51:27.830 回答
1

混淆来自于“通过引用传递”被人们误解或错误使用的事实。

参数按值传递。这意味着更改方法内部的值不会更改原始值。

在原语的情况下,原语的价值就是它的价值。在对象的情况下,对象的值是对它的引用。您可以访问和更改对象的内容,但不能更改引用本身的值。

在其他编程语言中,如 C++ 或 C#,“通过引用传递”意味着您传递: - 对原始类型的引用 - 对对象引用的引用 在这种情况下,不仅可以更改对象的内容而且引用本身也可以更改。

Javascript 中没有引用传递。

于 2013-09-14T11:58:58.513 回答
1

Javascript 使用pass-by-value

令人困惑的是对象由引用变量(指针的种类)持有。事实上,大多数常用语言(java、javascript 等)都没有真正的按引用传递行为。另一种理解这一点的方法可能是pass-reference-by-value,尽管从形式上讲,没有这样的事情。

这意味着当您将对象作为参数传递时,您实际上是在传递对对象的引用by-value

function setName2(obj) {
  ...
}

setName2(person);

这里person(引用或“指针”,如果你喜欢)的内容按值复制到一个新的局部变量:obj.

obj并且person是持有对同一对象的引用的不同变量。

因此,doesobj = new Object();指向obj新对象。但是person不受影响,因为它仍然是一个完全不同的变量。

于 2013-09-14T12:14:56.663 回答
0

我不知道你从哪里读到的,但这绝对不是真的。对象通过引用传递,句号。它是否是函数参数完全无关紧要。

于 2013-09-14T11:51:09.097 回答