-
Notifications
You must be signed in to change notification settings - Fork 1.4k
seek and destroy
Tran edited this page Nov 30, 2018
·
2 revisions
- 这个
function
接收多个参数。第一个参数为数组arr
,即为需要操作的原数组。后续的参数均表示需要删除的元素。返回值为操作后的数组 - 比如接收的是
[1, 2, 3, 1, 2, 3]
与2
,3
,那么返回值为[1, 1]
。 - 需要注意的是,如果分割的过程出现剩余,那么返回值的最后一个数组会比较短。比如接收的是
[1, 2, 3]
与2
,那么输出就是[[1, 2], [3]]
- 上一道题目中我们用循环造了个
filter
的轮子。这道题同样可以通过手写循环来完成,思路与上一道题基本一致。只是这道题,我们是在操作一个数组与不定数量的数字 - 如果你不知道
arguments
是什么,请先点开上面的链接了解一下,否则代码是没法写的 - 请一定要注意
arguments
的类型,不能认为它就是一个数组,其实它只是一个很接近数组的对象。但一定要明白,你是不可以在arguments
上直接调用数组方法的 - 但你可以在
arguments
上通过index
来获取某一个参数。而且,arguments
自带了一个.length
属性 - 既然我们要在数组中删除元素,因此
splice
是有必要的。当然我们也可以创建一个空数组,然后把符合条件的元素push
进去。这里就只给出splice
的写法吧
function destroyer(arr) {
// 先把 arguments 转换为数组
var arg = [].slice.call(arguments);
// 保存下来第一个参数,就是要操作的数组
var sourceArr = arg[0];
// 后续的参数均为需要删除的数字,我们也把这些数字放到一个数组里
var refArr = arg.slice(1);
// 可以思考一下,这里为什么不能从 0 开始遍历
for (var i = sourceArr.length - 1; i >= 0; i--) {
// 如果当前的元素存在于 refArr 中,就把它删掉
if (refArr.indexOf(sourceArr[i]) > -1) {
sourceArr.splice(i, 1);
}
}
return sourceArr;
}
- 首先,对于
[].slice.call(arguments)
这个写法,同样可以换成Array.prototype.slice.call(arguments)
。作用相同,都是把arguments
转换成一个数组。能理解这个写法的原理最好,如果不能理解,请把它背下来 - 通过
arg[0]
,我们可以得到传入的所有参数中的第一个参数,也就是要操作的数组 - 通过
arg.slice(1)
,我们可以得到除了第一个参数以外,后续的所有参数 - 平时写循环,我们都习惯从 0 开始遍历。但这里,可以试一下,如果从 0 开始遍历是会出错的。原因很简单,如果我们删除了某一个元素,那么在这之后的所有元素的
index
都会减一。然后我们通过i++
来进入下一次循环,相当于跳过了一个元素 - 解决方案很简单,那就是从右边开始遍历。因此有了上面的写法
function destroyer(arr) {
var sourceArr = arguments[0];
var refArr = [].slice.call(arguments, 1);
return sourceArr.filter(function (e) {
return refArr.indexOf(e) === -1;
})
}
- 这里我们直接通过
.call(arguments, 1)
来获取后续参数。我们可以把这段代码理解成arguments.slice(1)
,但这样写是肯定会报错的,因为arguments
并没有slice
这个数组方法 - 使用
filter
,过滤掉不在refArr
中的元素,就可以得到我们想要的结果
function destroyer(arr) {
return [].slice.call(arguments).reduce(function (prev, next) {
return prev.filter(function (e) {
return e !== next;
});
});
}
- 如果不能理解这个写法,请先点击上面的链接,看看
reduce
是如何使用的 - 这里我们把
reduce
的返回值设置为prev
经过filter
操作后的结果,并用于下次计算。next
则为arguments
中,除了第一个元素以外的其他元素 - 由于这里我们没有在
reduce
中传入第二个参数,也就是默认值。因此,进入reduce
后,第一次调用的prev
就是arguments
中的第一个参数,也就是我们要操作的数组