3

1340.640.jpg

引言

今天小K问了我一个面试题,怎么实现一个实reverse方法,在实现的过程中我还是犯了一些错,实现完以后,对一些知识点的理解又加深了。

错误的写法

最开始我是这么写的

var arr = [1,2,3,4,5]
    var reverse1 = function (arr) {
      let newArr = []
      while (arr.length>0){
        newArr.push(arr.pop())
      }
      console.log(arr,newArr) // [],[5,4,3,2,1]
      arr = newArr //让arr等于反转后的新数组
      console.log(arr) // [5,4,3,2,1]
      return arr
    }
    reverse1(arr)

结果有点打脸

console.log(arr) // []

函数参数的传递方式

上面的现象显示:我将arr当参数传入reverse1里面,我可以改变arr里面的内容但是我却无法改变arr(arr由[1,2,3,4,5]pop()五次变成[ ],但是随后的赋值操作却没有成功)
为什么会出现这个问题,我们得从函数的参数传递方式说起

函数的参数都是值传递

怎么理解这句话,按照高程的说法,如果这里是引用传递,那么我在代码第8行已经让arr变成了[5,4,3,2,1],那么外面的arr也应该变,但是现在外面arr却是[ ],所以函数的参数的传递方法都是值传递

如果你觉得这么说还是比较抽象,你可以听听鄙人陋见,我们完全可以把js里面数组名当成一个指针变量,储存的是实际的数组对象的地址。指针意味着我们通过它可以访问它指向的对象。变量意味者我可以改变这个变量。

在函数参数里面当我们传入一个arr的时候,实际传递的是一个形参address1,储存arr这个对象在内存里的地址,address1=xxxx xxxxx xxxx xxx1。通过address1可以对arr进行任何操作,一旦现在我为address1赋上新的地址值,也就是address1=xxxx xxxxx xxxx xxx2。address1就和arr失去了联系。此时arr还是在xxxx xxxxx xxxx xxx1上,并且至少在当前的reverse1方法中不会再被改变了,因为没有哪个指针能指向它了。

正确的写法

ok说了这么多,实际想说的是,你在方法中可以通过索引,通过原生方法操作一个当参数传进来的数组,但是绝对不允许对数组名直接进行赋值
那么这个题目我们就可以尝试使用原生方法来操作传进来的数组,这里提供一种思路

var arr = [1,2,3,4,5]
var reverse1 = function () {
      for(var i = 0; i < arr.length; i ++){
        arr.splice(i,0,arr.pop())
      }
    }
reverse1(arr)
console.log(arr) // [5,4,3,2,1]

但是我们可以看到上面的方法还是不是很好,这是因为这个reverse1貌似只能对arr进行操作,耦合性太强,我们需要解耦,让reverse1对所有的数组都适用,这里适用this和原型方面的知识

//一个完美的写法:
Array.prototype.reverse1 = function () {
      for(var i = 0; i < this.length; i ++){ //this 解耦
        this.splice(i,0,this.pop())
      }
      return this
    }

总结

今天介绍了一下reverse的实现思路,this解耦,以及函数参数是值传递这么一个概念,
建议在方法中通过索引,通过原生方法改变一个当参数传进来的数组,但是绝对不允许对数组名直接进行赋值
希望对大家有所帮助。


Runningfyy
1.3k 声望661 粉丝