12

我一直假设 Javascript 中有原始类型和引用类型。在日常的基础上,我从来没有对我产生过这种影响,但我刚刚开始使用更多的 JS,并想更新我的“想法”。换句话说,我会下注 20 美元,以下将返回 68

var my_obj = {};
var tmp_obj = {};

tmp_obj.my_int = 38;
my_obj.tmp_val = tmp_obj.my_int;
tmp_obj.my_int = 68;

alert('68 means reference, 38 means primitve: ' + my_obj.tmp_val);

但它返回 38。

在此处输入图像描述

即使数字类型的所有实例都存在于引用类型的上下文中,它们是否都是原始类型?如果是的话,我真的很惊讶并发现这种奇怪的行为(并且会损失 20 美元)。还是我的例子没有展示我的想法?

提前谢谢

更新#1

哇,谢谢所有的答案。这是一个微小的变化,对我理解有很大帮助:

var my_obj={};
var tmp_obj={};
var my_obj_2=tmp_obj;
tmp_obj.my_int=38;
my_obj.tmp_val=tmp_obj.my_int;
tmp_obj.my_int=68
alert('68 means reference, 38 means primitve: ' + my_obj.tmp_val);   // 38
alert('68 means reference, 38 means primitve: ' + my_obj_2.my_int);  // 68
my_obj_2.my_int=78;
alert(tmp_obj.my_int); // tmp_obj is now 78 ie two way
4

5 回答 5

7

如果您有,您的示例将按预期工作

     my_obj = tmp_obj;

然后,所有属性都将指向同一个引用,因为只有一个对象。

但是当你写

     my_obj.tmp_val = tmp_obj.my_int;

然后my_obj.tmp_val将采用存储在tmp_obj.my_int其中但不会在 2 个对象之间创建新引用的值。

于 2013-01-21T16:55:57.067 回答
6

如果我可以使用类似 Java 的语法,您似乎希望代码表现得像这样,其中有一个整数对象的值发生了变异。

tmp_obj.my_int = new Integer(38);
my_obj.tmp_val = tmp_obj.my_int;
tmp_obj.my_int.setValue(68);

由于它不打印,因此68您得出结论整数必须是原始类型而不是引用类型。不过,这不一定遵循。考虑这种替代解释:

tmp_obj.my_int = new Integer(38);
my_obj.tmp_val = tmp_obj.my_int;
tmp_obj.my_int = new Integer(68);

这里整数是引用类型,但my_obj.tmp_val仍将包含 value 38,因为分配给整数意味着覆盖引用。

您可以将整数视为不可变对象。JavaScript 在呈现统一的“一切皆为对象”视图方面做得非常好,因此这比“整数是原始类型”更好地解释了结果。

于 2013-01-21T16:56:23.077 回答
4

是的,像数字和字符串这样的值就像原始值一样工作。它们是不可变的。为变量分配新值会替换旧值,它不会更改那里的值。

例子:

var x = 42;
var y = x; // y == 42
x = 1337; // this puts a new value in x, it doesn't change 42 to be 1337
alert(y); // it's still 42

同样适用于字符串:

var x = "42";
var y = x; // y == "42"
x = "1337"; // this puts a new string in x, it doesn't change "42" to be "1337"
alert(y); // it's still "42"

另外,如果您使用对象属性;

var o = {};
o.x = 42;
o.y = o.x; // o.y == 42
o.x = 1337; // this puts a new value in o.x, it doesn't change 42 to be 1337
alert(o.y); // it's still 42

值的行为方式仅取决于其类型,而不是存储在常规变量中还是对象的属性中。

即使字符串在内部实现为对象,它也是不可变的并且作为值工作。复制字符串可能会复制对对象的引用,但效果是您获得了单独的副本,因为没有任何东西可以更改字符串值本身。

于 2013-01-21T17:00:25.130 回答
3

我一直假设 Javascript 中有原始类型和引用类型。

确实如此。但是,唯一的参考值是对象;原始值是不可变的。

即使数字类型的所有实例都存在于引用类型的上下文中,它们是否都是原始类型?

是的。他们的背景是不相关的。

于 2013-01-21T16:56:10.543 回答
2

我相信这里有两个关键的事情要理解:

  1. 原始值永远不是引用
  2. JavaScript 引用永远不能被分配,只能被复制。

考虑这段代码来演示第一点:

var a = 10,
    b = a,
    c = {foo : 20}
    d = c.foo;

b = 20;
d = 30;
a;     // 10;
c.foo; // 20;

所以,你有“槽”(变量或属性)保存原始值,而不是引用。更改其中一个插槽中的值不会影响其他插槽。

考虑第二点:

var a = {foo: true},
    b = a;
b.foo; // true
b.foo = false;
a.foo; // false;
b = {bar: false};
a;     // {foo: false}

变量a包含一个对象,并且b最初是对同一对象的引用。分配给b.foo影响a,因为ba指向完全相同的对象。但是,这些引用就像存储在给定插槽中的任何其他值一样:当您将其他内容分配给插槽时,引用只是被替换为不同的值。所以分配给b不会影响a.

于 2013-01-21T17:04:10.313 回答