共计 1476 个字符,预计需要花费 4 分钟才能阅读完成。
引言
今天小 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 解耦,以及函数参数是值传递这么一个概念,建议在方法中通过索引,通过原生方法改变一个当参数传进来的数组,但是绝对不允许对数组名直接进行赋值希望对大家有所帮助。