请指教下为啥输出的不是[1,2,3]

var a = [1];
function f(a){
a[100] = 3;
a = [1,2,3];
}
f(a)
console.log(a);
阅读 2k
4 个回答

这是面向对象和形参的问题啦,js 里的数组也是对象。

一步一步的看:

var a = [1]  // a 指向 objectX,objectX 的内容是 `[1]`
function f(a) {
    // 这里的 a 是形参,你把它换成 b 也没什么不同,b 也指向 objectX,objectX 的内容是 `[1]` 
    
    a[100] = 3  // b 还指向 objectX,objectX 的内容变成了 `[1, ..., 3]`
    a = [1, 2, 3]  // b 指向了 objectY 了,objectY 的内容是 `[1, 2, 3]`
}
f(a)
console.log(a) // a 指的还是 objectX

如果你把 fn(a) 换成 fn(),结果就会和你期待的一样了。

  1. 先理解基本类型和引用类型。比如你要买水果分2种形式 1.直接去水果店(基本类型-直接操作内存)2.用饿了吗买(饿了吗是一个指针, 指向水果店(内存))
  2. 假设你非常清楚这基本类型和引用类型, 理解形参和实参
    假设你要找人B给你买水果(这个动作就是f这个函数) 这个人B需要知道你要去哪个水果店买(形参), 你告诉他要用饿了吗去[水果店A]买 (这个过程B拿到的是饿了吗这个指针)
  3. B在买水果的时候给你在[水果店A]下单了(a[100] = 3;) 然后在饿了吗上换了一个水果店C(a = [1,2,3];)
  4. 但是你给的指令是在饿了吗上的[水果店A]买,所以你只能得到(a[100] = 3;), 水果店C买的你拿不到

... 逗一下 。下面严谨的回答

首先在a = [1, 2, 3] 这个步骤之前。这个形参a接受到的其实就是实参a的指针,如第一位同学说的,这个形参a你随便换都可以,这也是为什么叫形参的原因,只是一个接受者
a = [1, 2, 3]这个操作叫赋值操作,赋值操作按照值的类型给等号左边的变量分配一个新的地址(或者指针),因此这个时候a有一个新的指针了,不会再指向原来的数组。

你要好好学习一下作用域了!
1: 里面的a 指的是 function的 参数a, 相当于里面 var a = a;
2: 里面的a 改变身上的元素 是改变地址指向的数组, 所以共同改变
3: a = [xxx] 是把内部的a重写了, a已经不指向 外部的a了

Js中参数传递的方式是 值传递
var a = [1]; // 声明引用类型时,变量a保存的是内存地址,这个地址里放入的才是数组[1],函数和对象同理;

  1. 对于基本类型的值来说,比如string、number、boolean,调用函数的时候是直接拷贝一份数据给函数内部使用,函数内对参数的修改不会影响函数外的值。
  2. 对于引用数据的值来说,比如function、array、object,拿描述中的数组a来说,调用函数f的时候,也是将a拷贝一份传入,但是拷贝的是数组a的地址,而不是a数组本身。所以目前看来,函数内的a和函数外的a指向同一个数组的地址,所以a[100] = 3这句代码会对函数外的a产生影响,但是执行a = [1, 2, 3],相当于创建一个新数组,将新数组的地址赋给a,直接切断了函数内的a和外部a数组的联系,所以到现在,函数内的a和函数外的a不再指向同一个地址。
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题