引言
今天小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解耦,以及函数参数是值传递这么一个概念,
建议在方法中通过索引,通过原生方法改变一个当参数传进来的数组,但是绝对不允许对数组名直接进行赋值
希望对大家有所帮助。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。