数组:
在对象的基础上,只关注值,不关注健,需要元素有序排列,可以获取长度,可以根据上一个,找到下一个。
缺陷:牺牲了键,查找速度变慢,增删都会导致数组重新排列,效率降低。
数组创建方式:
//字面量创建
var arr=[];
// 构造函数创建
var arr1=new Array();
var arr2=Array();
// 对象创建
var arr3=new Object([]);
声明变量arr,赋给arr数组的引用地址,数组中元素有对应下标,下标从0开始,因此,数组最后一位下标为数组长度-1(数组长度不定可变,因此数组长度可读可写)
for in 与 for 的区别:
for in用来遍历对象,以key遍历value
数组没有key,只有value,但是数组是基于对象创建的,因此数组的下标可以看为对象的key,使用for in遍历数组时,会把下标转换为字符串,通过对象的遍历方式,查询所有的元素,在对象查找时,key和value是一对的,有key和value才可以被枚举,只有key,没有value是不可能被枚举的,数组也是对象,如果数组增加属性和方法,也会被for in所遍历枚举
for循环,只能根据下标循环,不能根据key,所以不能枚举属性,但是根据下标,会得到控制
arr.length=200;//赋值长度
arr.length=5//当数组的长度小于原数组长度时,默认将数组的超出元素清除
arr.length--;//删除数组的最后一个元素
arr.length=0;//将数组清空
arr=[];//新建了一个数组赋值,原有数组在堆中流浪了。。。(内存泄漏)
数组方法重构:
-
push方法重构:
/* 功能分析:数组尾部添加新元素,并返回数组新长度 实现分析: 确定所给元素是否是数组,确定数组是否存在→数组尾部添加元素→返回数组新长度 */ function arrayPush(arr){ if(!arr) throw new Error("Cannot read property 'push' of undefined"); if(arr.constructor !== Array) throw new Error("arr.push is not a function"); let i = 0; while(i++ < arguments.length){ arr[arr.length] = arguments[i]; } return arr.length; } /* var arr = [1,2,3]; console.log(arrayPush(arr,4,5)); console.log(arr); */
-
pop方法重构:
/* 功能分析:删除数组最后一位元素并将其返回 实现分析:确定所给元素是否是数组,确定数组是否存在→确定数组是否为空→删除数组最后一位元素→返回被删除元素 */ function arrayPop(arr){ if(!arr) throw new Error("Cannot read property 'pop' of undefined"); if(arr.constructor !== Array) throw new Error("arr.pop is not a function"); if(arr.length === 0) return; let item = arr[arr.length - 1]; arr.length--; return item; } /* var arr = [1,2,3]; console.log(arrayPop(arr)); console.log(arr); */
-
shift方法重构:
/* 功能分析:删除数组第零项元素并将其返回 实现分析:确定所给元素是否为数组,确定数组是否存在→确定数组是否为空→取出数组第零项元素→数组元素前移→数组长度-1→返回被删除元素 */ function arrayShift(arr){ if(!arr) throw new Error("Cannot read property 'shift' of undefined"); if(arr.constructor !== Array) throw new Error("arr.shift is not a function"); if(arr.length === 0) return; let item = arr[0],i = 0; while(i<arr.length){ arr[i] = arr[i + 1]; i++; } arr.length--; return item; } /* var arr = [1,2,3]; console.log(arrayShift(arr)); console.log(arr); */
-
unshift方法重构:
/* 功能分析:数组头部添加若干元素,并返回数组新长度 实现分析:确定所给元素是否为数组,确定数组是否存在→确认是否有添加元素→确认数组新长度并扩充数组→数组原有元素后移→添加元素置入数组头部→返回数组新长度 */ /* //有点冗余: function arrayUnshift(arr) { if (!arr) throw new Error("Cannot read property 'unshift' of undefined"); if (arr.constructor !== Array) throw new Error("arr.unshift is not a function"); if (arguments.length < 2) return arr.length; let len = arr.length - 1; arr.length += arguments.length - 1; let i = arr.length - 1; while (i >= arguments.length - 1) { arr[i] = arr[len]; i--; len--; } i = 0; while (i < arguments.length - 1) { arr[i] = arguments[i + 1]; i++; } return arr.length; } */ //优化: function arrayUnshift(arr) { if (!arr) throw new Error("Cannot read property 'unshift' of undefined"); if (arr.constructor !== Array) throw new Error("arr.unshift is not a function"); if (arguments.length < 2) return arr.length; let len = arr.length - 1; arr.length += arguments.length - 1; let i = arr.length - 1, j = 0; while (true) { if (i >= arguments.length - 1) { arr[i] = arr[len]; i--; len--; } else { arr[j] = arguments[j + 1]; j++; if (j === arguments.length - 1) break; } } return arr.length; } /* 思路对比: function arrayUnshift(arr){ if(!arr || arr.constructor!==Array) throw new Error("arr is not Array Type"); arr.length+=arguments.length-1 var n=arr.length-1; while(n>=0){ if(n>=arguments.length-1) arr[n]=arr[n-(arguments.length-1)]; else arr[n]=arguments[n+1]; n--; } return arr.length; */ /* let arr = [1, 2, 3]; console.log(arrayUnshift(arr, 4, 5, 6)); console.log(arr); */
-
concat方法重构:
/* 功能分析:将原数组与一个或多个元素/数组合并产生新数组并返回,不填写参数,则复制原数组 实现分析:确认数组是否存在,确认元素是否为数组→创建新数组,复制原数组→确认参数列表,无参数则将新数组返回→确认参数元素是否有数组,无则直接加入新数组尾部→有则遍历参数元素数组,将其元素加入新数组→返回新数组 */ function arrayConcat(arr){ if (!arr) throw new Error("Cannot read property 'concat' of undefined"); if (arr.constructor !== Array) throw new Error("arr.concat is not a function"); let i = arr.length,arr1 = []; while(i-- > 0){ arr1[i] = arr[i]; } if(arguments.length < 2) renturn arr1; while(i++ < arguments.length - 1){ if(arguments[i].construcotr === Array){ for(let j = 0;j < arguments[i].length;j++){ arr1[arr1.length] = arguments[i][j]; } }else arr1[arr1.length] = arguments[i]; } return arr1; } /* let arr = []; console.log(arrayConcat(arr,1, [1, 2])); */
-
join方法重构:
/* 功能分析:将数组元素提出,按照指定分隔符分离形成字符串(默认为逗号),返回字符串,不影响原数组 实现分析:确认数组是否存在,确认元素是否为数组→创建空符号串→确认数组是否为空,为空则直接返回符号串→确认参数列表是否定义分隔符,否则默认为逗号→将数组元素依次加入字符串并以分隔符分隔,如果元素为undefined,则加入一个空格→返回字符串 */ function arrayJoin(arr){ if (!arr) throw new Error("Cannot read property 'join' of undefined"); if (arr.constructor !== Array) throw new Error("arr.join is not a function"); let str = ""; let separator = arguments[1]; if (separator === undefined) separator = ","; for(let i = 0; i < arr.length; i++){ if (!arr[i]) str += separator; else if (i !== arr.length - 1) str += arr[i] + separator; else str += arr[i]; } return str; } /* let arr = [1,2,3]; console.log(arrayJoin(arr,"!")); */
-
slice方法重构:
/* 功能分析:提取数组中指定部分形成新数组并返回,不影响原数组 实现分析:确认数组是否存在,确认元素是否为数组→确认参数列表,为空则复制整个数组,确认起始位置和终止位置→复制指定数组元素,置入新数组→返回新数组 */ function arraySlice(arr,start,end){ if (!arr) throw new Error("Cannot read property 'slice' of undefined"); if (arr.constructor !== Array) throw new Error("arr.slice is not a function"); let arr1 = []; if(start === undefined) start = 0; if(end === undefined) end = arr.length; start = ~~start,end = ~~end; if(start < 0) start += arr.length > -start ? arr.length : -start; if(end < 0) end += arr.length; if(end < 0) return arr1; for(let i = start;i < end;i++){ arr1[arr1.length] = arr[i]; } return arr1; } /* let arr = [1, 2, 3, 4, 5]; console.log(arraySlice(arr, 2, 4)); */
-
forEach方法重构:
/* 功能分析:遍历数组每个元素,并传给回调函数,但是对于空数组不会执行回调函数 实现分析:确认数组是否存在,确认元素是否为数组→确认函数是否存在,确认元素是否为函数→确认参数列表,确认数组遍历起点,无则默认从头开始→遍历数组元素,并传递给回调函数 */ function arrayForEach(arr,fn){ if(!arr || arr.constructor!==Array) throw new Error("arr is not Array Type"); if(!fn || fn.constructor!==Function) throw new Error("undefined is not a function"); for(var i=0;i<arr.length;i++){ if(i in arr) fn(arr[i],i,arr); } } /* arrayForEach(arr,function(item,index,arr){ console.log(item,index,arr); }); */
-
map方法重构:
/* 功能分析:返回一个新数组,长度与原来相等,map中回调函数中使用return可以将需要的每个元素数据返回给新数组中对应的位置,但是对于空数组不会执行回调函数,不改变原数组 实现分析:确认数组是否存在,确认元素是否为数组→声明空数组→遍历数组元素,并传递给回调函数→返回新数组 */ function arrayMap(arr,fn){ if(!arr || arr.constructor!==Array) throw new Error("arr is not Array Type"); if(!fn || fn.constructor!==Function) throw new Error("undefined is not a function"); var arr1=[]; for(var i=0;i<arr.length;i++){ if(i in arr) arr1[i]=fn(arr[i],i,arr); } return arr1; } /* var arr = [1,2,3,4,5]; var arr1=arrayMap(arr,function(item){ return item+10; }) console.log(arr1); */
-
splice方法重构:
//目前还存在bug,后续更新修改 /* 功能分析:向数组指定位置添加/删除元素,如果删除了元素,则返回被删除元素的数组 实现步骤分析: 声明一个空数组,用于存储数组被删除元素 判断参数是否是数组 确认是否给入指定起始位置,没有则返回声明的空数组 将起始位置转换为数值类型 如果起始位置为非数值类型,则默认从第0位开始,如果起始位置小于0,则从起始位置+数组长度开始,如果仍小于0,则从第0位开始,如果起始位置大于数组长度,则起始位置等于数组长度 确认是否给入删除元素数量,没有则为从起始位置到数组元素最后一位的元素数量 将删除元素数量转换为数值类型,如果删除元素数量为非数值类型,则默认删除数量为0,如果删除数量小于0,则返回声明的空数组,如果删除数量+起始位置大于数组长度,则删除数量为从起始位置到数组元素最后一位的元素数量 遍历数组,从起始位置开始删除指定数量的元素 确认新数组长度 确认参数列表中是否有添加元素内容,有则添加至数组尾部 返回被删除元素数组 */ function array_splice(arr, start, deleteCount) { var arr1 = []; if (!arr || arr.constructor !== Array) throw new Error("参数错误"); if (start === undefined) return arr1; start = Number(start); if (isNaN(start)) start = 0; if (start < 0) start = start + arr.length < 0 ? 0 : start + arr.length; if (start > arr.length) start = arr.length; if (deleteCount === undefined) deleteCount = arr.length - start; deleteCount = Number(deleteCount); if (isNaN(deleteCount)) deleteCount = 0; if (deleteCount < 0) return arr1; if (deleteCount + start > arr.length) deleteCount = arr.length - start; for (var i = start; i < arr.length; i++) { if (i < deleteCount + start) arr1[arr1.length] = arr[i]; arr[i] = arr[i + deleteCount]; } arr.length -= deleteCount; var len = arguments.length - 3; var l = (arr.length += len); while (l > start) { if (l > start + len) arr[l - 1] = arr[l - len - 1]; else arr[l - 1] = arguments[3 + (l - 1 - start)]; l--; } return arr1; }