类数组ArrayLike、数组的长度是会去动态的改变的、去除数组重复数据多种方法
一、类数组ArrayLike
参照:https://www.cnblogs.com/guorange/p/6668440.html。
如果类数组的length和属性乱七八糟的?
1.啥叫类数组?
拥有length属性,其它属性(索引)为非负整数(对象中的索引会被当做字符串来处理,这里你可以当做是个非负整数串来理解)的对象。
不具有数组所具有的方法。
类数组转为数组可以使用数组的很多方法。
example1
//类数组示例
var a = {'1':'a','2':'b','5':'c',length:5};
example2
//判断是否是类数组
function isArrayLike(o) {
if (o && // o is not null, undefined, etc.
typeof o === 'object' && // o is an object
isFinite(o.length) && // o.length is a finite number
o.length >= 0 && // o.length is non-negative
o.length===Math.floor(o.length) && // o.length is an integer
o.length < 4294967296) // o.length < 2^32
return true; // Then o is array-like
else
return false; // Otherwise it is not
}
js中常见的类数组有arguments
对象和DOM方法返回的结果。
比如document.getElementsByTagName()
.
2.类数组转为数组的方法
example3
var arraylike = {'1':'a','2':'b','5':'c',length:5};
var arr = Array.prototype.slice.call(arraylike);
console.log(arr);//[empty, "a", "b", empty × 2]
arr = [].slice.call(arraylike);
console.log(arr);//[empty, "a", "b", empty × 2]
arr = [].splice.call(arraylike,0);
console.log(arr);//[empty, "a", "b", empty × 2]
方法不唯一,这里只是将数组的slice方法的this指针替换了,然后将类数组作为原来的数组来执行slice等方法。灵位可以发现类数组丢失了一个属性,所以不是所有类数组转为数组都是完整的,属性大小不能超出或等于length的长度(我猜的)。不过一般都可以。
slice方法的内部实现如下:
example4
//slice的内部实现
Array.prototype.slice = function(start,end){
var result = new Array();
start = start || 0;
end = end || this.length; //this指向调用的对象,当用了call后,能够改变this的指向,也就是指向传进来的对象,这是关键
for(var i = start; i < end; i++){
result.push(this[i]);
}
return result;
}
3.数组转为类数组
example5
function convertArrayLike(arr){
var obj = arr.reduce(function(prev,cur,curindex,array){
return prev[curindex] = cur,prev;
},{});
return obj.length = arr.length,obj;
}
var arr = [1,2,3,1,2,6];
console.log(convertArrayLike(arr));//{0: 1, 1: 2, 2: 3, 3: 1, 4: 2, 5: 6, length: 6}
二、数组的长度是会去动态的改变的
看一个问题,如下:
example6
var arr = [1,2,3,4,5];
for(var i = 0;i < arr.length;i++){
//删除第i+1个元素(删除第i个元素起的1个元素,返回删除的元素数组)
arr.splice(i, 1);
}
console.log(arr);//[2, 4]
这里我们想删光所有数组元素,但结果却不是想象的那样,因为数组删掉一个元素后,可能会对下一步循环的寻找的元素有影响,解决方法如下:
example7
var arr = [1,2,3,4,5];
for(var i = arr.length;i > 0;i--){
//删除最后一个元素
arr.splice(i-1, 1);
}
console.log(arr);//[]
三、去除数组重复数据多种方法
思维锻炼
example8
function unique(arr){
for(var i = 0;i < arr.length;i++){
for(var j = arr.length-1;j > i;j--){
arr[i] === arr[j] ? arr.splice(j,1):null;
}
}
}
var arr = [1,2,3,4,3,2,1];
unique(arr)||console.log(arr);// [1, 2, 3, 4] unique()方法返回undefined,即为false
两边遍历,删掉重复的右边。不过这个方法会改变原有的数组。
example9
function unique(arr){
var temp = [];
for(var i = 0;i < arr.length;i++){
for(var j = 0;j < temp.length;j++){
if(arr[i] === temp[j]) break;
}
if(temp.length == j){
temp.push(arr[i]);
}
}
return temp;
}
var arr = [1,2,3,3,3,2,1];
var arr2 = [];
console.log(unique(arr));//[1,2,3]
console.log(unique(arr2));//[]
没啥说的。
example10
function unique(arr){
var temp = [];
for(var i = 0;i < arr.length;i++){
if(temp.indexOf(arr[i]) == -1)
temp.push(arr[i]);
}
return temp;
}
var arr = [1,2,3,3,3,2,1];
var arr2 = [];
console.log(unique(arr))//[1, 2, 3]
console.log(unique(arr2));//[]
这里用了数组的indexOf方法,所以在ie低版本有兼容问题。
example11
function unique(arr){
return arr.filter(function(item,index,array){
// return index == array.lastIndexOf(item);
return array.indexOf(item,index+1) == -1;
});
}
var arr = [1,2,3,3,3,2,1];
var arr2 = [];
console.log(unique(arr))//[3, 2, 1]
console.log(unique(arr2));//[]
第二个return是将最右边的重复的保留。
example12
function unique(arr){
return arr.sort(function(a,b){
return a-b;
}).filter(function(item,index,array){
return item != array[index+1];
});
}
var arr = [1,2,3,3,3,2,1];
var arr2 = [];
console.log(unique(arr))//[1, 2, 3]
console.log(unique(arr2));//[]
先排序,再将最右边(最右边特征是与他的下一个元素不等)的过滤出来。
example13
function unique(arr){
var obj = {};
return arr.filter(function(item,index,array){
return obj[item] ? false : obj[item] = true ;
},{});
}
var arr = [1,2,3,3,3,2,1];
var arr2 = [];
console.log(unique(arr))//[1, 2, 3]
console.log(unique(arr2));//[]
利用对象的特性过滤重复属性。
example14
function unique(arr){
return Array.from(new Set(arr));
}
var arr = [1,2,3,3,3,2,1];
var arr2 = [];
console.log(unique(arr))//[1, 2, 3]
console.log(unique(arr2));//[]
利用set的特性(不可重复)去重。
综上,所有方法中,第1,2和最后一个兼容性较好。