一、判断数组方法总结
-
通过
Object.prototype.toString.call()
每一个继承 Object 的对象都有
toString
方法,如果toString()
没有重写的话,会返回[Object type]
,其中 type 为对象的类型。但当除了 Object 类型的对象外,其他类型直接使用toString()
时,会直接返回都是内容的字符串,所以我们需要使用call或者apply方法来改变toString()
的执行上下文。// 这种方法对于所有基本的数据类型都能进行判断,即使是 null 和 undefined ;常用于判断浏览器内置对象时。 Object.prototype.toString.call(['Hello','An']); // "[object Array]" Object.prototype.toString.call('An') // "[object String]" Object.prototype.toString.call(1) // "[object Number]" Object.prototype.toString.call(Symbol(1)) // "[object Symbol]" Object.prototype.toString.call(null) // "[object Null]" Object.prototype.toString.call(undefined) // "[object Undefined]" Object.prototype.toString.call(function(){}) // "[object Function]" Object.prototype.toString.call({name: 'An'}) // "[object Object]" 复制代码
-
通过
instanceof
[] instanceof Array; // true 复制代码
-
instanceof 原理
能在实例的 原型对象链 中找到该构造函数的prototype
所指向的 原型对象,就返回true
。即:// __proto__: 代表原型对象链 instance.[__proto__...] === instance.constructor.prototype // return true 复制代码
-
-
通过ES6
Array.isArrray()
function isArray(obj){ return Array.isArrray(obj); }; 复制代码
-
instanceof 与 isArray
当检测Array实例时,
Array.isArray
优于instanceof
,因为Array.isArray
可以检测出iframes
-
Array.isArray()
与Object.prototype.toString.call()
Array.isArray()
是ES6新增的方法,当不存在Array.isArray()
,可以用Object.prototype.toString.call()
实现。
-
4、通过原型链来判断
5、通过Array.prototype.isPrototypeOf
二、数组常用方法
join()
: 通过指定连接符生成字符串
2.1 栈方法
栈是一种 LIFO(Last-In-First-Out,后进先出)的数据结构,也就是最新添加的项最早被移除。而栈的插入(叫做推入)和移除(叫做弹出),只发生在一个位置——栈的顶部。
push() / pop()
:数组末尾推入和弹出,改变原数组;push
返回修改后的数组长度,pop
返回移除的项。
2.2 队列方法
队列数据结构的访问规则是 FIFO(First-In-First-Out,先进先出)。队列在列表的末端添加项,从列表的前端移除项。
shift()
:移除数组中的第一项并返回该项,改变原数组;unshift()
:在数组前端添加任意个项并返回新数组长度,改变原数组;
2.3 重排序方法
-
reverse()
:反转数组的顺序,改变原数组; -
sort()
:默认会采用升序排列数组项,但是为了实现排序,sort()
会调用每个数组项的toString()
,然后比较得到的字符串,改变原数组var arr = [0, 1, 5, 10, 15]; arr.sort(); // arr=>[0, 1, 10, 15, 5] // sort()方法可接收一个比较函数作为参数; function compare(val1,val2){ return val1-val2; } arr.sort(compare); // arr => [0, 1, 5, 10, 15] 复制代码
2.4 操作方法
-
concat()
: 可以基于当前数组中的所有项创建一个新数组。即这个方法会先创建当前数组的一个副本,然后将接收到的参数添加到这个副本的末尾,最后返回新构建的数组。连接数组,(不影响原数组),浅拷贝 -
slice(start, end)
:基于当前数组中的一个或多个项创建一个新数组。(不改变原数组)- 一个参数时,返回从该参数指定位置开始到当前数组末尾的所有项;
- 两个参数时,返回起始和结束位置之间的项——但不包含结束位置的项;
- 如果参数有负值,则用数组长度加上该数来确定相应的位置;如果结束位置小于起始位置,返回 []
-
splice(start, number, value...)
:主要用途是向数组的中部插入项,改变原数组- 删除:指定 2 个参数,即要删除第一项的位置和要删除的项数;
- 插入:指定 3 个参数,即起始位置、0(要删除的项数)和要插入的项。可插入多个项;
- 替换:指定 3 个参数,即起始位置、要删除的项数和要插入的任意数量的项。
2.5 位置方法
indexOf / lastIndexOf(value, fromIndex)
: 查找数组项,返回对应的下标
2.6 迭代方法
每个方法都接收两个参数,即要在每一项上运行的函数和(可选的)运行该函数的作用域对象——影响 this 的值
传入这些方法中的函数会接收 3 个参数:数组项的值、该项在数组中的位置和数组对象本身。
every()
:如果该函数对每一项都返回 true ,则返回 true;some()
:如果该函数对任一项返回true
,则返回true
;filter()
:返回该函数会返回 true 的项组成的数组;forEach()
:这个方法没有返回值;无法break
,可以用try/catch
中throw new Error
来停止map()
:返回每次函数调用的结果组成的数组;
2.7 归并方法
reduce()
和reduceRight()
这两个方法都会迭代数组的所有项,然后构建一个最终返回的值。都接受两个参数:一个在每一项上调用的函数和(可选的)作为归并基础的初始值。
方法中的函数接收 4 个参数:前一个值、当前值、项的索引和数组对象;这个函数返回的任何值都会作为第一个参数自动传给下一项。第一次迭代发生在数组的第二项,所以第一个参数是数组的第一项,第二个参数是数组的第二项。
-
reduce()
:从数组的第一项开始,逐个遍历到最后; -
reduceRight(fn(prev, cur), defaultPrev)
: 两两执行,prev 为上次化简函数的return
值- 当传入
defaultPrev
时,从第一项开始; - 当未传入时,则为第二项
// 使用 reduce() 执行求数组中所有值的和; var arr = [1,2,3,4,5]; var sum = arr.reduce(function(prev,cur,index,array){ return prev+cur; }) // 15 复制代码
- 当传入
三、数组去重
(1)for循环嵌套,然后splice方法去重
思路:双层循环,外层循环元素,内层循环时比较值,值相同时删除这个值;(ES5中实用)
function unique(arr){
for(var i=0;i<arr.length;i++){
for(var j=i+1;j<arr.length;j++){
if(arr[i]==arr[j]){
arr.splice(j,1);
j--;
}
}
}
return arr;
}
var arr=[1,2,3,3,4];
console.log(unique(arr)); //==>1,2,3,4
复制代码
(2)新建数组,利用indexOf去重
思路:新建一个数组,原数组遍历传入新数组,判断值是否存在,值不存在就加入该新数组中;但是,方法“indexOf”是es5的方法,IE8以下不支持。(es5中较简单)
function unique2(arr){
var newArr = []; //一个新的临时数组
for(var i = 0; i < arr.length; i++){ //遍历当前数组
//如果当前数组的第i已经保存进了临时数组,那么跳过,否则把当前项push到临时数组里面
if (newArr.indexOf(arr[i]) == -1){
newArr.push(arr[i])
};
}
return newArr;
}
复制代码
(3)ES6中利用Set高级函数去重
function newArr(arr){
return Array.from(new Set(arr))
// Array.from()方法就是将一个类数组对象或者可遍历对象转换成一个真正的数组
}
var arr = [1,1,2,9,6,9,6,3,1,4,5];
console.log(newArr(arr))
//这种方法还无法去掉“{}”空对象
复制代码
(4)使用数组自带的filter()
;
function unique(arr) {
return arr.filter(function(item, index, arr) {
//当前元素,在原始数组中的第一个索引==当前索引值,否则返回当前元素
return arr.indexOf(item) === index;
});
}
var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}];
console.log(unique(arr))
//[1, "true", true, 15, false, undefined, null, "NaN", 0, "a", {…}, {…}]
复制代码
(5)利用sort()
思路:先将原数组进行排序,然后对排序后的数组的相邻项进行比较;
缺点:排序改变了原数组;
function unique(arr) {
arr = arr.sort(); //sort()方法改变了原数组;
var newArr = [arr[0]];
for (var i = 1; i < arr.length; i++) {
if (arr[i] !== arr[i - 1]) {
newArr.push(arr[i])
}
}
return newArr;
}
复制代码
四、数组的扁平化flatern
将一个多层级的数组[[1,2], 3, [4,5, [6,7, [8, 9, [10, 11]]]]]
按顺序展开到一个数组中.数组的扁平化
function flatern(arr){
const isArray = arr.some(item => return item instanceof Array)
if(!isArray) {
return arr
}
const res = Array.prototype.concat.apply([], arr)
return flatern(res)
}
// 方法二:
const flatten = arr => {
return arr.reduce((pre, next) => {
return pre.concat(Array.isArray(next) ? flatten(next) : next);
}, []);
};
复制代码