js函数参数问题;

今天在开发的时候,后端返回一个json对象,其中一个list数组是个数组需要我从新构建;
代码简单整理长这样;

let obj = { list: [1,2,34]}
    function resolveList(list) {
        list=[];
        //.......处理list的代码,后续list
        // [{},{},{}] list 
    }
    resolves(obj.list)

我想着我传的是个引用类型,后续的obj.list应该已经构建好了;但是后面打印发现obj.list并没有改变;其中坏就坏在
list=[];
这里不置空list直接用拿到的参数list处理,也是ok的。obj.list也是有值的; list=[];以后值就没改变。我大概想了一下,可能是这样把list定义到全局了,参数的list被覆盖了。然后我在全局打印了list,然而全局也没有list这是我最费解的;
请教下各路彦祖,1,我的list的这个指针为什么会丢失,2,如果是被list=[]覆盖那么为啥全局又没发现这个list

阅读 5k
7 个回答

你不能这样写,你要这样写:

function resolveList(obj) {
   obj.list=[];
}

或者

function resolveList(list) {
   list.length = 0
}

对于resolveList的参数来说,他就是一个普通局部变量,当你执行resolves(obj.list)的时候,这个普通变量保存了obj.list的引用,然后,你再执行list=[]的时候,这时候这个普通变量就断掉了对obj.list的引用,改为保存[]的引用,这时候你拿list进行操作,这些操作都打不到obj.list上。

因此,如果你想让参数保存对外部对象的引用,就不能对参数进行直接赋值操作。

obj.list=[]的话,因为obj没有被直接赋值,因此依然保持对外部对象的引用,所以可以很顺利的通过这个引用,把外部对象下的list属性给改了。

然后是list.length=0的话,还是一样的道理,list没有被直接赋值,依然保持对外部对象的引用,通过给其属性length设置为0的方式,让外部数组的长度变为0,从而丢弃掉数组里面的所有值。

因此,你这两个问题的答案:

  1. 你对参数赋值之后,参数断掉了与原来数组的引用。相当c语言的操作里,你拿到一个指针,然后把指针的地址给改了,自然就找不到原来的对象了。
  2. js函数的参数相当于一个局部变量,在函数体内部生效,并不会挂载到全局上。

JS 的引用和 C++ 的引用概念有所不同,它是一个单向传递的关系,更像是 C++ 的指针。所以你改变了它的值(list = [])实际是改变了局部变量(形参),对外面的 list 引用(实参)没有影响。

js赋值是传址的,址为内存地址。

那意思就很明显,你的函数内 list 指针 实际上还是 obj.list 的地址。

即你 list = [] 就直接修改了原 obj.list 内容。

函数参数是本地类型的,那么该参数是按值传递,也就是复制

let a=1;
function add (p){
return p++
}
add(a)
log(a)//还是1

函数参数是引用类型的,参数就是引用的原对象

let obj = { list: [1,2,34]}
    function resolveList(list) {
        list=[];
        //.......处理list的代码,后续list
        // [{},{},{}] list 
    }
    resolves(obj.list)

函数体内的 list=[] 等同于 obj.list=[]
因为这个list就是引用的obj.list

你这里这个逻辑本身就有问题啊

    let obj = { list: [1,2,34]}
    function resolveList(list) {
        list=[];// 这里肯定不能这样写,一写就覆盖了传递来的list参数值,你可以改成 _list=[]; 
        //.......处理list的代码,后续list
        // [{},{},{}] list 
    }
    resolves(obj.list) //因为要传递的实际参数是对象,所以说引用传参,如果函数中有不恰当的处理,原始值也可能会被影响。但你只是把list重新赋值了,相当于list=new Array(),这时list指向了一个新的空数组,而原来的数组(obj.list)没有变。

不过我更想说的是你代码意图其实很不明确。

从你贴出来的代码看,没懂你为啥要修改函数参数的值呢?一般是不建议直接去修改参数的值的。可以新建一个变量去操作,不要直接修改参数 list.

新手上路,请多包涵

从代码里可以看出,resolveList拿到的是个值,并非引用类型

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题