var foo = 1,
bar = foo;
bar = 9;
console.log(foo, bar); // => 1, 9
var foo = [1, 2],
bar = foo;
bar[0] = 9;
console.log(foo[0], bar[0]); // => 9, 9
var foo = [1, 2],
foo = bar;
bar[0] = 9;
console.log(foo[0], bar[0]); // => 9, 9
第二、三中为什么会输出9,9?
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号
理解这个区别的关键就是理解
bar = 9
和bar[0] = 9
的区别。先说
bar = 9
,这等于是说:将一个对象(数字 9)赋值给变量bar
。在此之前,bar
和foo
都是指向数字 1 的引用,但是bar = 9
这一句等于重写了bar
的指向。所以foo
是 1,bar
是 9。再说
bar[0] = 9
,首先bar
和foo
一样都是数组 [1, 2] 的引用(换言之,它们指向的是同一个数组对象),那么bar[0] = 9
并没有改变bar
本身的指向,而是把它所指向的数组的第一个元素改成 9。即使数组里的第一个元素的值改变了,bar
和foo
依然还是指向这同一个数组。所以foo[0]
是 9,bar[0]
也是 9。本问题可以归根结底为数据和变量的对应关系。
在C/Java之类的编程语言里,我们可以很清楚地区分"赋值/赋引用"、"传值/传引用":
=
操作符赋值则内存中两个变量各自保存一份数据;
赋引用内存中只有一份数据。
传值则会在内存中拷贝出第二份数据,用于函数修改,不影响原有的数据;
传引用则不会在内存中拷贝出第二份数据,函数直接修改目标内存地址中的数据。
我们看区分这两个过程的用例:
很明显,
=
以后,两个变量各自保存一份数据(1和9),否则不会出现数字的不一致。hence, 赋值。没有改变变量的数据,函数执行上下文中拷贝出来了一份x,要不然这里的结果就应该是1了。hence, 传值。
纵观楼主的用例,出现了传值和传引用两种结果,这是由于JavaScript中有Primitive Value和Object的区别的缘故。
那么我们是否可以得出结论了?
如果要浅显地记忆,到这里就差不多了。
下面是非常非常容易混淆的分界线。
Primitive Value可以见MDN定义。
一个关键词是,immutable values,不可改变。
这个定义即意味着他们作为传参和
=
操作符对象时,值本身不会修改。在JS引擎执行的同一个生命周期里,
1
不会变成2
;"google"
不会变成"google+"
——immutable的实现方式,是引用。从这个意义来说,@nighttire的解释是正确的(尽管“对象”不准确,正确的说法是“引用”)。再次解释JavaScript内的”赋值/赋引用”、”传值/传引用”:
=
操作符两个变量各自保存同一个引用
函数传参
则内存中开辟一个新的变量空间,储存原有参数的引用
(还记得JavaScript那个经典的闭包问题吗,函数调用过程中,会拷贝一份参数的引用,才会直接或间接调用函数的方案)
感觉到混淆了吗,C/C++中对值和引用的区分,在表述中完全没有必要,因为JavaScript里面,从始至终,只有引用。
那么,在这些用例里面,是什么造成了最终的结果差异?答案是,是否允许变化。
LZ的赋值用例
传参用例
这是一个典型的引用类型(对象)进行复制的问题。
参考:
刚才贴了一张图,重新梳理一下。
这是一个典型的变量复制问题,引出两个概念:值传递和引用传递。
直接看代码:
分析一下每一步
foo
和bar
的结果就很好理解了。关键字:
不知道javascript高级程序设计这里为什么用
可能
两个字...但是大致可归纳,一般来说对象是引用类型;其他的基本类型是不引用的,就如你的第一段代码的效果。引用类型
楼上的图很形象,数组也是对象
另一个哥们的回答怎么转眼就不见了?