数组基础
原文:http://www.ferecord.com/lujs-array.html
简介
数组是应用最广泛的数据存储结构。它被植入到大部分编程语言中。在 ECMAScript 中数组是非常常用的引用类型。
属性
length
length属性表示数组的长度,即其中元素的个数。
JavaScript数组的length属性是可变的,当length属性被设置得更大时,整个数组的状态事实上不会发生变化,仅仅是length属性变大;当length属性被设置得比原来小时,则原先数组中索引大于或等于length的元素的值全部被丢失。
prototype
返回对象类型原型的引用。prototype 属性是 object 共有的。
一般用来给数组实例添加方法。
constructor
表示创建对象的函数。
说明:constructor 属性是所有具有 prototype 的对象的成员。constructor 属性保存了对构造特定对象实例的函数的引用。
基本操作
创建数组
| 12345678910 | // 数组实例的创建var arr = []var arr = new Array() //创建一个空数组 []var arr = new Array(5) //创建一个length为5的数组 [undefined, undefined, undefined, undefined, undefined]var arr = new Array(1,2,3,4,5) //创建数组并赋值 [1,2,3,4,5] var arr = Array.of(7); // 创建数组并赋值 [7]var arr = Array.of(1, 2, 3); // 创建数组并赋值 [1, 2, 3] |
检测数组
| 12345678 | //判断一个对象是不是数组var arr = []if(arr instanceof Array){} // 方法一if(Object.prototype.toString.call(arr) == ‘[object Array]’)}{} // 方法二if(Array.isArray(arr)){} //方法三if(arr.constructor == Array){} // 方法四 |
数组方法 isArray, from, of
Array.isArray(obj)
检测对象是否 Array ,是则返回true,否则为false。
Array.from(arrayLike, mapFn, thisArg)
该方法从一个类似数组或可迭代对象创建一个新的数组实例。参数 arrayLike 是想要转换成真实数组的类数组对象或可遍历对象。mapFn 是可选参数,如果指定了该参数,则最后生成的数组会经过该函数的加工处理后再返回。thisArg是可选参数,为执行 mapFn 函数时 this 的值。
所谓类似数组的对象,本质特征只有一点,即必须有length属性。因此,任何有length属性的对象,都可以通过Array.from方法转为数组。
实际应用中,常见的类似数组的对象是 DOM 操作返回的 NodeList 集合,以及函数内部的 arguments 对象。
| 12345678910111213141516 | let arrayLike = { 0: ‘a’, 1: ‘b’, 2: ‘c’, length: 3}let arrayLike2 = {length: 3}let str = ‘abcd’ let newArray = Array.from(arrayLike) //[‘a’, ‘b’, ‘c’]let newArray2 = Array.from(arrayLike, (v) => v+’1’) //[‘a1’, ‘b1’, ‘c1’]let newArray3 = Array.from(arrayLike2) // [undefined, undefined, undefined]let newArray4 = Array.from(str) // [‘a’, ‘b’, ‘c’, ‘d’] |
Array.of(item…)
该方法用于创建数组实例。该方法用于替代 Array() 或 new Array()。Array.of() 和 Array 构造函数之间的区别在于处理整数参数:Array.of(7) 创建一个具有单个元素 7 的数组,而 Array(7) 创建一个包含 7 个 undefined 元素的数组。
| 1234567 | Array.of(7); // [7]Array.of(1, 2, 3); // [1, 2, 3] Array(7); // [ , , , , , , ]Array(1, 2, 3); // [1, 2, 3] |
数组实例方法
转换方法 join
arr.join(separator)
把数组构构造成字符串,它先把数组中的每个元素转换成字符串,然后再用 separator 分隔符把它们链接在一起,separator 分隔符默认是逗号 “,”,要想做到无间隔链接,可以使用空字符串作为 separator:
| 1234567 | var arr = [1,2,3,4,5]arr.join(‘|’) //“1|2|3|4|5”arr.join(“”) //12345 //另所有对象有具有的 toLocaleString、toString、valueOf,可以看作是join的特殊用法,不常用 |
栈方法 push, pop
arr.push(item…)
将一个或多个新元素添加到数组结尾,并返回数组新长度。
arr.pop()
移除最后一个元素并返回该元素值。
队列方法 unshift, shift
arr.unshift(item…)
将一个或多个新元素添加到数组开始,数组中的元素自动后移,返回数组新长度。
arr.shift()
移除最前一个元素并返回该元素值,数组中元素自动前移.如果这个数组是空的,它会返回 undefined。shift 通常比 pop 慢的多。
重排序方法 reverse, sort
arr.reverse()
反转数组的顺序。
arr.sort(comparefn)
给数组排序,默认升序。
注意 sort 默认会将数组内容视为字符串来排序,所以对数字排序时默认的排序规则会错的离谱。一般我们给sort带入个比较函数来替代原来的默认的比较方法,比较方法接受两个参数,如果两个参数相等则返回0,如果第一个参数应该排在前面则返回一个负数,如果第二个参数应该排在前面则返回一个正数:
| 1234567 | //数组排序var arr = [2,3,1,5,4]arr.sort(function(a, b) { return a - b}) // [1,2,3,4,5] |
操作方法 concat, slice, splice, copyWithin, fill
arr.concat(item…)
该方法产生一份 arr 的潜复制,并将多个数组(也可以是字符串,或者是数组和字符串的混合)附加在其后连接为一个数组,返回连接好的新的数组。
arr.slice(start, end)
该方法对数组中的一段做浅复制,首先复制数组 arr[start] 至 arr[end] 的部分,注意不包括 end 对应的元素,如果省略 end 将复制 start 之后的所有元素(或者理解成 end 的默认值为 arr.length)。字符串也有个同名方法 string.slice。
arr.splice(start, deleteCount, item…)
该方法从 arr 中移除一个或多个元素,并将新的 item 插入至移除元素的开始位置, 参数 start 是移除元素的开始位置,deleteCount 是要移除的元素的个数,item 是要被插入的元素。它返回一个包含被移除元素的数组。
arr.copyWithin(target, start, end)
该方法复制数组的一部分到同一数组中的另一个位置(会覆盖原成员),并返回修改后的数组。使用这个方法,会修改当前数组。参数 target 为开始替换数据的位置,若 target 大于等于 arr.length,将会不发生拷贝。start 是可选参数,为开始读取数据的位置,默认为0。end 是可选参数,为停止读取数据的位置,默认为 arr.length。
| 1234 | [1, 2, 3, 4, 5].copyWithin(0, 3)// [4, 5, 3, 4, 5] |
上面代码表示将从3号位直到数组结束的成员(4和5),复制到从0号位开始的位置,结果覆盖了原来的1和2。
arr.fill(value, start, end)
该方法使用给定值填充一个数组,参数 value 是用来填充数组的值。start 是可选参数,为填充开始位置,默认为 0。end 是可选参数,为填充的结束位置,默认为 arr.length。
| 1234 | [1, 2, 3].fill(4) // [4, 4, 4][1, 2, 3].fill(4, 1 , 2) // [1, 4, 3] |
fill 方法是个可变方法, 它会改变调用它的 this 对象本身, 然后返回它, 而并不是返回一个副本。
位置方法 indexOf, lastIndexOf, includes
arr.indexOf(searchElement, start)
该方法返回要查找的项在数组中的位置,如果没找到返回 -1。接受两个参数,searchElement 是要查找的项,start 是查找起始位置的索引,默认是0。
arr.lastIndexOf(searchElement, start)
从 start 位置开始向前查找,start 默认值为 arr.length - 1。
注意该方法在比较查找项与数组中每一项时,会使用全等操作符,也就是要求查找的项必须严格相等。
arr.includes(searchElement, fromIndex)
该方法用来判断当前数组是否包含某指定的值,如果是,则返回 true,否则返回 false。参数 searchElement 为需要查找的元素值。参数 fromIndex 是可选参数,从该索引处开始查找 searchElement,如果为负值,则按升序从 array.length + fromIndex 的索引开始搜索,默认为 0。 如果fromIndex 大于等于数组长度 ,则返回 false 。该数组不会被搜索。
该方法属于ES7,但Babel转码器已经支持。
| 12345 | [1, 2, 3].includes(2); // true[1, 2, 3].includes(4); // false[1, 2, NaN].includes(NaN); // true |
没有该方法之前,我们通常使用数组的indexOf方法,检查是否包含某个值。
| 12345 | if (arr.indexOf(el) !== -1) { // …} |
indexOf方法有两个缺点,一是不够语义化,它的含义是找到参数值的第一个出现位置,所以要去比较是否不等于-1,表达起来不够直观。二是,它内部使用严格相当运算符(===)进行判断,这会导致对NaN的误判。includes使用的是不一样的判断算法,就没有这个问题。
| 123456 | [NaN].indexOf(NaN)// -1[NaN].includes(NaN)// true |
includes() 方法有意设计为通用方法。它不要求this值是数组对象,所以它可以被用于其他类型的对象 (比如类数组对象)。
| 123456 | (function(){ console.log([].includes.call(arguments, 2)) // true console.log([].includes.call(arguments, 4)) // false})(1,2,3) |
迭代方法 every, some, filter, forEach, map, find, findIndex, entries, keys, values
arr.every(callback,thisArg)
对数组中的每一项运行给定函数,如果该函数对每一项都返回 true,则返回 true。callback 被调用时传入三个参数:元素值,元素的索引,原数组。thisArg 为可选参数,指定执行 callback 时使用的 this 值。
arr.some(callback, thisArg)
对数组中的每一项运行给定函数,如果该函数对任意一项返回 true,则返回 true。
arr.filter(callback, thisArg)
对数组中的每一项运行给定函数,返回该函数会返回 true 的项组成的数组。
arr.forEach(callback)
对数组中的每一项运行给定函数,这个方法没有返回值。本质上与使用 for 循环迭代数组一样。
arr.map(callback)
对数组中的每一项运行给定函数,返回每次函数调用组成的数组。
arr.find(callback, thisArg)
该方法对数组所有成员依次执行 callback 函数,直到找出第一个返回值为 true 的成员,然后返回该成员。如果没有符合条件的成员,则返回 undefined。
| 1234 | [1, 4, -5, 10].find((v, i, arr) => v < 0)// -5 |
find方法的回调函数可以接受三个参数,依次为当前的值、当前的位置和原数组
arr.findIndex(callback, thisArg)
该方法与 arr.find() 类似,对数组中的成员依次执行 callback 函数,直至照吃第一个返回值为 true 的成员,然后返回该成员的索引。如果没有符合条件的成员,则返回 -1。
| 123456 | [1, 5, 10, 15].findIndex((v, i , arr)=>{ return v > 9})//2 |
arr.entries()arr.keys()arr.values()
这三个方法都返回一个新的Array Iterator对象,可以用for...of循环进行遍历,区别是keys()是对键名的遍历、values()是对键值的遍历,entries()是对键值对的遍历。
| 123456789101112131415161718192021 | for (let index of [‘a’, ‘b’].keys()) { console.log(index); }// 0// 1 for (let elem of [‘a’, ‘b’].values()) { console.log(elem) ;}// ‘a’// ‘b’ for (let [index, elem] of [‘a’, ‘b’].entries()) { console.log(index, elem);}// 0 “a”// 1 “b” var arr = [“a”, “b”;var iterator = arr.entries(); // undefined console.log(iterator); // Array Iterator {} console.log(iterator.next().value); // [0, “a”]console.log(iterator.next().value); // [1, “b”] |
归并方法 reduce, reduceRight
arr.reduce(callback, initialValue)arr.reduceRight(callback, initialValue)
这个两个方法都会迭代数组所有的项,然后返回一个最终值。reduce()方法从数组的第一项开始,逐个遍历到最后,而reduceRight()则从数组的最后一项开始,向前遍历到第一项。它们接受两个参数,callback 每一项上调用的函数,callback 被调用时传入四个参数:上一次调用回调返回的值、正在处理的元素、正在处理的元素的索引值(如果提供了 initialValue ,从0开始;否则从1开始)、原数组。initialValue 是可选项,作为归并基础的初始值,其值用于第一次调用 callback 的第一个参数。
数组常见问题练习
数组合并
多个一维数组合并
如有两个一维数组,要将他们合并成一个数组:
| 123456 | var arr1 = [1, 2]var arr2 = [3, 4] // => [1,2,3,4] |
Array.prototype.concat()方法
| 123 | var arr = arr1.concat(arr2) //[1, 2, 3, 4] |
for循环和Array.prototype.push()
| 12345678 | function flation(arr1, arr2) { for (var i = 0; i < arr2.length; i++) { arr1.push(arr2[i]) } return arr1} |
reduce()或reduceRight()方法
| 123456789 | function flatten(arr1, arr2) { return arr2.reduce(function (prev, curr) { prev.push(curr) return prev }, arr1)} |
多维(复合)数组合并成一维数组
例如有这么一组多维数组,要把它拍平成1维数组:
| 12345 | var myArray = [[1, 2], [3, 4, 5], [6, 7, 8, 9], [11,12,[12,13,[14]]], 10, 11]; // => [1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 12, 13, 14, 10, 11] |
Array.prototype.push()方法
| 1234567891011121314151617 | function flatten(arr, result) { if (!result) { result = [] } for (var i = 0; i < arr.length; i++) { if(arr[i].constructor == Array) { flatten(arr[i], r) } else { result.push(arr[i]) } } return result}flatten([[1, 2], [3, 4, 5], [6, 7, 8, 9], [11,12,[12,13,[14]]], 10, 11])//[1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 12, 13, 14, 10, 11] |
Array.prototype.concat()方法
| 123456789101112 | //省略对二维以上数组的判断function flatten(arr) { var result = [] for (var i = 0; i < arr.length; i++) { result = result.concat(arr[i]) } return result}flatten([[1, 2],[3, 4, 5], [6, 7, 8, 9]]);//[1, 2, 3, 4, 5, 6, 7, 8, 9]flatten([[1, 2],[3, 4, 5], [6, 7, 8, 9],10,11]);//[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11] |
可以通过Function.prototype.apply()方法,让其变得更简单:
| 123456 | //省略对二维以上数组的判断function flatten(arr) { return Array.prototype.concat.apply([], arr)} |
还可以将上面方法做个精简:
| 123456 | //省略对二维以上数组的判断function flatten(arr) { return [].concat.apply([], arr)} |
在 ES6 中,还可以这样写:
| 123456 | //省略对二维以上数组的判断function flatten(arr) { return [].concat(…arr)} |
如果要处理三维或更多维数组,则需要加一些判断:
| 12345678 | function flatten(arr) { arr = [].concat.apply([], arr) return arr.some(Array.isArray) ? flatten(arr) : arr}flatten([[1, 2], [3, 4, 5], [6, 7, 8, 9], [11,12,[12,13,[14]]], 10, 11])//[1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 12, 13, 14, 10, 11] |
或者:
function flatten(arr) {
var isArray = Object.prototype.toString.call(arr) == ‘[object Array]’;
| 123456789 | if (isArray && arr.length > 0) { var head = arr[0] var tail = arr.slice(1) return flatten(head).concat(flatten(tail));} else { return [].concat(arr)} |
}
使用join()和split()
利用数组实例的join()方法和字符串实例的split()方法,也可以将多维数组拍平:
| 1234567 | function flatten(arr) { return arr.join(‘,’).split(‘,’)}flatten([[1, 2], [3, 4, 5], [6, 7, 8, 9], [11,12,[12,13,[14]]], 10, 11])//[“1”, “2”, “3”, “4”, “5”, “6”, “7”, “8”, “9”, “11”, “12”, “12”, “13”, “14”, “10”, “11”] |
这种方法的缺点在于返回的数组内全是字符串,如果不需要校验内容类型的话,可以使用这种方法。
数组去重
双重循环去重
思路:
- 构建一个空数组来存放去重后的数组
- 对原数组做循环遍历,每次从数组中取出一个元素与结果数组做对比
- 如果原数组取出的元素与结果数组元素相同,则跳出循环;反之则将其存放到结果数组
| 123456789101112131415161718192021 | function unique(arr) { var result = [arr[0]] for (var i = 1; i < arr.length; i++) { var repeat = false for (var j = 0; j < result.length; j++) { if (arr[i] == result[j]) { repeat = true break; } } if (!repeat) { result.push(arr[i]) } } return result} unique([1, 2, 3, 4, 3, 2, ‘a’, ‘b’, ‘a’]);//[1, 2, 3, 4, “a”, “b”] |
这种方法也可采用forEach()方法和indexOf()方法模拟实现:
| 12345678910111213 | function unique(arr) { var result = [arr[0]] arr.forEach(function(v) { if (result.indexOf(v) == -1) { //这里 indexOf()也可替换为es7的includes() result.push(v) } }) return result}unique([1, 2, 3, 4, 3, 2, ‘a’, ‘b’, ‘a’]);//[1, 2, 3, 4, “a”, “b”] |
排序遍历去重
思路:
- 构建一个空数组来存放去重后的数组
- 用
sort()方法对原数组做一个排序,排完序后对数组做遍历,检查数组中第 i 个元素与结果数组中最后一个元素是否相同,如果不同,则放到结果数组中。
| 12345678910111213 | function unique(arr) { arr.sort(); var result = [] for (var i = 0; i < arr.length; i++) { if (arr[i] !== result[result.length - 1]) { result.push(arr[i]) } } return result}unique([1, 2, 3, 4, 3, 2, ‘a’, ‘b’, ‘a’]); |
这种方法有两个特色:
- 去重后的数组会做排序,主要是因为原数在去重前做了排序
- 去重后的数组,与数字相同的数字字符无法区分,比如‘1’和1
对象键值对法
思路:
- 创建一个 js 对象及新数组
- 遍历原数组,每次取出一个元素与 js 对象的键作对比
- 如果不包含,将存入对象的元素的值推入到结果数组中,并将 object 对象中该属性名的值设为1
| 123456789101112131415 | function unique(arr) { var result = [] var object = {} for (var i = 0; i < arr.length; i++) { if (!object[typeof(arr[i]) + arr[i]]) { //键名里加入typeof(arr[i])是为了区别不同类型的值,如1和`1` result.push(arr[i]) object[typeof(arr[i]) + arr[i]] = 1 } } return result}unique([1, 2, 3, 4, 3, 2, ‘1’, ‘a’, ‘b’, ‘a’]);//[1, 2, 3, 4, “a”, “b”] |
这种方法比较耗内存,但运行下来耗时最少,是较为优秀的方案。
使用 ES6 的 Set 和 Map 方法
| 123456789101112131415 | //借助 Map 数据结构function unique(arr) { const seen = new Map() return arr.filter((v)=> !seen.has(v) && seen.set(v, 1));} //借助 Set 数据结构function unique(arr) { return Array.from(new Set(arr)) //或 return […new Set(arr)]} unique([1, 2, 3, 4, 3, 2, ‘1’, ‘a’, ‘b’, ‘a’]);//[1, 2, 3, 4, “1”, “a”, “b”] |
数组随机排序
递归的方法
思路:
不断从原数组中随机取一个元素放进新数组,同时删除原数组中该值,递归重复至全部取出。
| 1234567891011121314151617 | function randomSort(arr, newArr) { var newArr = newArr || [] if (arr.length == 1) { newArr.push(arr[0]) return newArr; // 相当于递归退出 } var random = Math.ceil(Math.random() * arr.length) - 1 newArr.push(arr[random]) arr.splice(random, 1) return randomSort(arr, newArr)}randomSort([1, 2, 3, 4, 5, 6, 7]); //[2, 3, 1, 5, 6, 7, 4]randomSort([1, 2, 3, 4, 5, 6, 7]); //[3, 4, 2, 5, 1, 6, 7] |
使用数组 sort 方法对数组元素随机排序(效果不佳)
思路:
使用srot()每次比较时返回一个随机值,让数组内元素依次前后随机排序
| 1234567891011 | Array.prototype.shuffle = function(n) { var len = this.length, num = n ? Math.min(n, len) : len, arr = this.slice(0) arr.sort(function(a, b){ return Math.random() - 0.5 }) return arr.slice(0, num)}[1, 2, 3, 4, 5, 6, 7].shuffle()//[1, 4, 2, 5, 6, 3, 7] |
这个方法虽然实现了随机排序,但由于sort()方法是依次比较的,所以每个元素被随机到原位置后面的概率会越来越低。
随机交换数组内的元素 (原理from underscore.js)
思路:
遍历数组,每次从i位置后元素随机挑一个放到i位置,将原i位置元素放至被挑元素原位置
| 1234567891011121314 | Array.prototype.shuffle = function() { var len = this.length, arr = this.slice(0), temp, index; for (var i = 0; i < len; i++) { index = i + Math.floor(Math.random() * (len - i)) temp = arr[i] arr[i] = arr[index] arr[index] = temp } return arr.slice(0)} |
随机从原数组抽取一个元素,加入到新数组
思路:
遍历数组,每次从数组中随机挑一个元素(随机数最大值为原数组剩余长度),将该元素拿出来放入新数组。
| 12345678910111213141516 | Array.prototype.shuffle = function() { var len = this.length, arr = this.slice(0), result = [], index; for (var i = 0; i < len; i++) { index = Math.floor(Math.random() * (len - i)) console.log(index) result.push(arr.splice(index, 1)[0]) } return result}[1, 2, 3, 4, 5, 6, 7].shuffle()//[5, 3, 2, 1, 7, 4, 6] |
取数组中最大值最小值
遍历比较方法
思路:
- 设一个变量存放最大值,将数组中第一个值赋值给该变量
- 遍历数组与最大值变量比较,如果大于最大值,则将该值赋值最大值变量
- 遍历结束后,变量里储存的就是数组里的最大值
| 12345678910 | Array.prototype.max = function() { var max = this[0] this.forEach(function(v) { if (v > max) {max = v} }) return max}[1,45,23,3,6,2,7,234,56].max() // 234 |
归并比较方法
思路:
- 使用数组实例的 reduce(function(prev, curv, index, arr)) 方法
- 依次比较回调函数中参数 prev 与 curv 的大小,返回大的那个
| 12345678 | Array.prototype.max = function() { return this.reduce(function(prev, curv) { return prev > curv ? prev : curv })}[1,45,23,3,6,2,7,234,56].max() // 234 |
利用 Math.max() 与 Math.min() 方法
思路:
将数组转换成参数传进Math.max()或Math.min()。
| 123456 | Array.prototype.max = function() { return Math.max.apply({},this) //或 return Math.max(…this)}[1,45,23,3,6,2,7,234,56].max() // 234 |
将一个数按大小顺序插入数组并返回索引值
任务:
构建一个函数where(arr, num),函数接受两个参数,一个是数组arr,一个是要插进数组的数字num,函数将num按大小顺序插进arr,并返回num的索引值。例如:
| 12345 | where([1,2,3,4], 1.5) //1where([20,3,5],19) //2where([40,60],50) //1 |
使用 push + sort + indexOf 方法
思路:
- 通过
push()或unshift()方法将 num 插入 arr - 使用
sort()对 arr 进行排序 - 使用
indexOf()找出 num 在 arr 中的 index(或使用for、forEach、some循环) - 返回 index
| 123456789101112 | function where(arr, num) { arr.push(num) arr.sort(function(a,b){ return a - b }) return arr.indexOf(num)}var a = [1,2,3,4]where(a, 1,5) //1, a = [1,1.5,2,3,4] |
或者:
| 12345678910111213141516171819 | function where(arr, num) { arr.push(num) arr.sort(function(a,b){ return a - b }) var index; arr.some(function(v,i) { if(v === num) { index = i return true } }) return index}var a = [1,2,3,4]where(a, 1,5) //1, a = [1,1.5,2,3,4] |
使用 sort + findIndex + splice 方法
思路:
- 使用
sort()对 arr 进行排序 - 使用 findIndex() 找出 arr 中第一个大于 num 的元素的位置
- 使用
splice()将 num 插入该元素前
| 1234567891011 | function where(arr, num) { arr.sort((a,b) => a-b) const index = arr.findIndex(v => v > num) arr.splice(index,0,num) return index} var a = [1,2,3,4]where(a, 1,5) //1, a = [1,1.5,2,3,4] |
从数组中寻找元素并删除元素
任务:
构建一个函数destroyer(arr, item…),传入数组与要删除的指定值,返回删除指定值后的数组,例如:
| 123 | destroyer([1,2,3,4,1,3,2],1,2) //[3,4,3] |
arguments + indexOf + filter 遍历判断法
思路:
- 通过 arguements 对象分别获取到数组 arr 和指定要删除的元素,将指定元素转换成数组 removeArgs
- 使用
filter()筛选出 arr 内与 removeArgs 内不相同的元素,筛选规则通过indexOf()方法判断
| 123456789101112131415161718 | function destroyer(para) { var arr = arguments[0] var removeArgs = [] for(var i = 1; i < arguments.length; i++) { removeArgs.push(arguments[i]) } var isFalse = function(v) { return removeArgs.indexOf(v) === -1 } return arr.filter(isFalse)} destroyer([1,2,3,4,1,3,2],1,2) //[3,4,3] |
slice(或解构运算符) + es6 set + filter 方法
思路:
- 利用
call()对 arguments 使用数组的slice()分别获取到原数组和指定值 - 将指定值传进 new Set 对象
- 使用
filter()筛选出 arr 内与 set 对象内不相同的元素,筛选规则通过 set 对象的has()方法判断
| 1234567 | function destroyer(para) { var removeArgs = new Set(Array.prototype.slice.call(arguments, 1)) return para.filter(v => !removeArgs.has(v))}destroyer([1,2,3,4,1,3,2],1,2) //[3,4,3] |
也可以写成:
| 1234567 | function destroyer(arr, …items) { var removeArgs = new Set(items) return arr.filter(v => !removeArgs.has(v))}destroyer([1,2,3,4,1,3,2],1,2) //[3,4,3] |