1 /** 2 * JS数组 3 * 类型:JS数组是无类型的,数组元素可以是任意类型 4 * 索引:基于零的32位数值,索引(下标)范围:0 到 (2的32次方)-2 [即 0 到 4 294 967 294], 5 * 即4 294 967 295个元素,在这个下标范围内,数组的 length 属性可以自动维护 6 * 特性: 7 * 1、动态;创建数组无需声明大小,其长度会根据需要动态增长或缩减 8 * 2、连续性:JS数组可能是稀疏的,元素索引不一定要连续 9 * 属性:length属性,表示数组长度(数组中数字索引的长度) 10 */ 11 12 /** 13 * 数组的创建: 14 * 1、使用直接量字符创建 15 * 2、调用构造函数 Array() 创建 16 */ 17 //使用数组直接量创建数组 18 var arr=[]; 19 20 // 数组的直接量的语法允许有可选逗号作结尾,直接量中被省略的值是不存在的, 21 //访问时会输出 undefined, 且直接量中的值不一定要是常量,也可以是表达式 22 var arr=[,,]; 23 console.log(arr);//[ <2 empty items> ] 这里数组为空,没有元素 24 //解析:上面语句实际上与 var arr=[,]; 相同 25 //第一个逗号左边和右边各有一个 item,第二个逗号可选(即可有可无) 26 27 var num=1024; 28 var arr=[undefined,undefined,++num]; 29 console.log(arr);//[ undefined, undefined, 1025 ] 30 //解析:这里的两个元素值为:undefined (这里数组有值,并不为空,只不过值刚好为:undefined) 31 32 //调用构造函数Array()创建数组 33 var arr=new Array();//[] 34 var arr=new Array(10);//[ <10 empty items> ] 指定数组长度为10 35 //var arr=new Array(4294967296);//RangeError: Invalid array length 36 //解析:数组索引范围(0 到 4 294 967 294),即4 294 967 295个元素,创建数组时超出范围报错 37 var arr=new Array(123,"abc",{});//[ 123, 'abc', {} ] //显式指定多个数组元素 38 39 /** 40 * 数组元素的读写: 41 * 数组是对象的特殊形式,使用方括号访问数组元素就像使用方括号访问对象的属性一样 42 * 数组索引和对象属性的区分: 43 * 1、所有索引都是属性名 44 * 2、只有在范围内(0 到 (2的32次方)-2)的整数属性名才是索引 45 * 3、因为所有数组都是对象,因此可以为数组创建任意名字的属性,如果使用的 46 * 属性名是数组索引(范围内的整数),那么数组就会根据需要更行它的 length 属性值 47 * 4、事实上数组索引仅仅是对象属性名的一种特殊情况,这意味着js数组没有"越界"错误概念 48 * 即当试图查询对象(数组是对象)中不存在的属性时,不会报错,只会得到 undefined 49 */ 50 var arr=[]; 51 arr[1]="num1"; 52 arr[2.000]="num2";//与 arr[2]="num2";相等 53 arr[-1.23]=true;//超出范围,不是索引,是属性 54 console.log(arr,arr[100]); 55 //[ <1 empty item>, 'num1', 'num2', '-1.23': true ] undefined 56 //解析:arr[0] 没有赋值,所以为空。arr[1],arr[2]对应数组索引。 57 //最后面的 '-1.23': true 就跟对象中的键值对一样,可通过 arr[-1.23]/arr["-1.23"] 访问到 58 //arr[100]超出当前数组的长度,但访问时不会报错,而是输出 undefined 59 60 61 /** 62 * 稀疏数组: 63 * 稀疏数组就是包含从0开始的不连续的索引的数组 64 */ 65 var arr=[]; 66 arr[20]="hello"; 67 console.log(arr,arr.length);//[ <20 empty items>, 'hello' ] 21 68 //解析:虽然数组长度为 21,但是数组是稀疏的,只有一个元素,前面元素全部为空 69 70 71 /** 72 * 数组的长度 length 属性: 73 * 更准确地说数组的 length 属性,表示的是数组中数字索引的长度,而不是数组中元素的个数 74 */ 75 76 var arr=[];//一个空数组,length=0 77 arr[3]="num3",arr["test"]="hello world",arr[-100]="-100"; 78 console.log("length:"+arr.length,arr); 79 //length:4 [ <3 empty items>, 'num3', test: 'hello world', '-100': '-100' ] 80 //解析:数组前面3个元素为空,arr[3]在上面赋值为 num3,后面两个不是索引,而是被当成对象属性 81 //数字索引有4个(arr[0]、arr[1]、arr[2]、arr[3]),也就说明:length 表示的是数组中数字索引的长度(这个就是数组长度) 82 //由此引出了下面这样一个特殊行为 83 84 //当设置 length 属性为一个小于当前数组长度的非负数n时,当前数组中那些索引值大于或等于n的元素将从中删除 85 //当设置 length 属性为一个大于当前数组长度的非负值n时,不会添加新元素,而是在数字索引元素后面添加空元素 86 var arr=new Array(1,2,3,4,5,6,7,8); 87 arr["a"]="a",arr["test"]="hello"; 88 console.log("length:"+arr.length,arr); 89 //length:8 [ 1, 2, 3, 4, 5, 6, 7, 8, a: 'a', test: 'hello' ] 90 91 arr.length=2; 92 console.log("length:"+arr.length,arr); 93 //length:2 [ 1, 2, a: 'a', test: 'hello' ] 94 //解析:可以看到索引arr[2]到arr[7]都被删除了,因为 length 表示的是数组中数字索引的长度(这个就是数组长度) 95 96 arr.length=5; 97 console.log("length:"+arr.length,arr); 98 //length:5 [ 1, 2, <3 empty items>, a: 'a', test: 'hello' ] 99 //解析:可以看到数组增加了3个空元素,且长度增加了,因为 length 表示的是数组中数字索引的长度(这个就是数组长度) 100 101 102 /** 103 * 数组的方法: 104 * join()、reverse()、sort()、concat()、slice()、splice()、 105 * push()、pop()、shift()、unshift()、toString()、toLocalString()、valueOf() 106 * forEach()、map()、filter()、every()、some() 107 * reduce()、reduceRight()、indexOf()、lastIndexOf() 108 */ 109 110 //join()方法,按指定字符串将数组中各个元素(这里指有索引的元素,下同)连接起来并返回 111 //始末状态:不会改变数组本身 112 //参数:分隔符 113 var data=[1,2,3,4,5,6,7,8]; 114 data["test"]="test"; 115 console.log(data.join(" @--> "));//1 @--> 2 @--> 3 @--> 4 @--> 5 @--> 6 @--> 7 @--> 8 116 console.log(data);//[ 1, 2, 3, 4, 5, 6, 7, 8, test: 'test' ] 不会改变数据本身 117 118 //reverse()方法,将数组中的元素倒序,并返回倒序后的数组(是倒序,不是从大到小排序,只是把元素位置倒转) 119 //始末状态:会改变数组本身 120 //参数:无 121 var data=[3,"d",1,"hello",{},-1,9,"b"]; 122 data["test"]="test"; 123 console.log(data.reverse());//[ 'b', 9, -1, {}, 'hello', 1, 'd', 3, test: 'test' ] 124 console.log(data);//[ 'b', 9, -1, {}, 'hello', 1, 'd', 3, test: 'test' ] 会改变数据本身 125 126 //sort()方法,将数组元素按指定顺序排序并返回排序后的数组,数组元素默认按照字母表顺序排序 127 //始末状态:会改变数组本身 128 //参数:可传入一个比较函数作为参数 129 var data=["z","x","p",5,4,3,2,1,12,19,25,21," ",""]; 130 data["test"]="test"; 131 console.log(data.sort()); 132 //[ '', ' ', 1, 12, 19, 2, 21, 25, 3, 4, 5, 'p', 'x', 'z', test: 'test' ] 133 //解析:虽然"2"的值比"12","19"要小,但是按照字符串比较时,"12","19",位于"2"前面,可以看出,数组元素默认按照字母表顺序排序 134 135 //比较函数,接受两个参数: 136 //如果第一个参数应该位于第二个之前则返回一个负数 137 //如果两个参数相等则返回0 138 //如果第一个参数应该位于第二个之后则返回一个正数 139 //原理:类似于冒泡排序 140 141 function compare(a,b){return a-b}//从小到大排序 142 var data=[5,4,3,2,1,12,19,25,21]; 143 data.sort(compare); 144 console.log(data);//[ 1, 2, 3, 4, 5, 12, 19, 21, 25 ] 145 146 //原理:如果把上面的比较函数稍加修改,并记录下比较次数和比较的元素, 147 //输出结果可以看到,一共调用了15次,每次将元素两两比较,仔细查看结果类似于冒泡排序 148 var count=0,result=""; 149 function compare(a, b) { 150 //other code 151 result+="#"+(++count)+"->"+a+"和"+b+"比较 "; 152 if (a < b) { 153 return -1; 154 } 155 else if (a > b) { 156 return 1; 157 } 158 else { 159 return 0; 160 } 161 //other code 162 } 163 console.log(result); 164 //#1->5和4比较 #2->5和3比较 #3->4和3比较 #4->5和2比较 #5->4和2比较 #6->3和2比较 #7->5和1比较 #8->4和1比较 165 //#9->3和1比较 #10->2和1比较 #11->5和12比较 #12->12和19比较 #13->19和25比较 #14->25和21比较 #15->19和21比较 166 167 // concat()方法,创建并返回一个新数组,新数组元素包括调用concat()方法的原始数组的元素和concat()中的每个参数 168 // 如果concat()参数中的任意一个参数是数组,则返回的是该数组中的元素,而不是该数组本身 169 // 始末状态:不会改变数组本身 170 // 参数:任意类型 171 var data=[1,2,3]; 172 console.log(data.concat(0,[11,22],[ 33, [44] , [ {} , [55] , "test"], 66] )); 173 //[ 1, 2, 3, 0, 11, 22, 33, [ 44 ], [ {}, [ 55 ], 'test' ], 66 ] 174 //解析:(1,2,3)为数组原来的元素,所以直接返回,concat()中有3个参数,其中两个是数组,简化后相当于data.concat(0,[数组一],[数组二]) 175 //因此返回的是0,和[数组一]、[数组二]里面的元素(数组里面元素可以是任意类型,因此元素也可以是数组) 176 console.log(data);//[ 1, 2, 3 ] 177 178 //slice()方法,返回指定数组的一个片段或者子数组 179 //始末状态: 不会改变数组本身 180 //参数:可不带参数或一个参数或两个参数,只有一个参数时,返回指定位置开始到当前数组末尾的所有项,负数表示倒数第几个数 181 //参数一:截取字符串的起始位置 参数二:截取字符串的结束位置(截取时不包括该位置的字符) 不带参数:与 Array.prototype.slice(0)返回的结果一样 182 var data=[1,2,3,4,5,6,7,8]; 183 data["test"]="test"; 184 console.log(data.slice(3));//[ 4, 5, 6, 7, 8 ] 从下标位3的位置开始一直到数组末尾 185 console.log(data.slice(2,-1));//[ 3, 4, 5, 6 ] 从下标位2的位置开始一直到数组倒数第二个数(截取时不包括该位置的字符) 186 console.log(data);//[ 1, 2, 3, 4, 5, 6, 7, 8, test: 'test' ] 187 188 //splice()方法,在数组中插入或删除元素,返回在数组中删除的元素 189 //始末状态:会改变数组本身 190 //参数:可有一个或两个参数或多个,只有一个参数时,从起始位置到数组末尾的所有元素都将被删除(这里指有索引的元素,前面已经提过了) 191 //参数一:插入或删除的起始位置 参数二:从数组中删除的元素个数 参数二后面的参数:这些参数将会插入数组参数一中的位置 192 var data=[1,2,3,4,5,6,7,8]; 193 data["test"]="test"; 194 console.log(data.splice(6));//[ 7, 8 ] 195 console.log(data);//[ 1, 2, 3, 4, 5, 6, test: 'test' ] 196 console.log(data.splice(3,2));//[ 4, 5 ] 197 console.log(data);//[ 1, 2, 3, 6, test: 'test' ] 198 console.log(data.splice(2,0,11,[22],{}),data); 199 //输出:[] ,从下标为2的位置开始删除0个元素(即不删除),在将后面的参数插入数组,插入位置是下标2的位置(即参数一) 200 console.log(data);//[ 1, 2, 11, [ 22 ], {}, 3, 6, test: 'test' ] 201 202 //push()方法,在数组末尾添加参数,并返回修改后数组的长度(即length的值) 203 //始末状态:会改变数组本身 204 //参数:任意个任意类型的参数 205 var data=[1,2,3]; 206 data["test"]="test"; 207 console.log(data.push(4,[5],{}));//6 208 console.log(data);//[ 1, 2, 3, 4, [ 5 ], {}, test: 'test' ] 209 210 //pop()方法,删除并返回数组最后一个元素 211 //始末状态:会改变数组本身 212 //参数:无 213 var data=[1,2,3]; 214 data["test"]="test"; 215 console.log(data.pop());//3 删除被返回元素 3 216 console.log(data);//[ 1, 2, test: 'test' ] 217 218 //unshift()方法,与push()类似,只不过添加的参数是在数组开头 219 //shift()方法,与pop()类似,只不过删除的参数是在数组开头 220 221 //forEach()方法,对数组中的每一项运行给定函数,无返回值 222 //始末状态:不会改变数组本身 223 //参数:给定的函数 224 //函数参数:可以有3个参数,参数一:当前数组元素 参数二:当前元素索引 参数三:数组本身 225 var data=[1,2,3,{}]; 226 var count=0; 227 data["test"]="test"; 228 console.log(data.forEach(function(item,index,arr){count++;}));//undefined 无返回值 229 console.log(data,"count:"+count);//[ 1, 2, 3, {}, test: 'test' ] 'count:4' 可以看出循环了4次 230 231 //map()方法,将数组每个元素传递给指定函数,返回一个数组,该数组包含指定函数的返回值 232 //始末状态:不会改变数组本身 233 //参数:给定的函数 234 //函数参数:可以有3个参数,参数一:当前数组元素 参数二:当前元素索引 参数三:数组本身 235 var data=[1,2,3,4,5]; 236 data["test"]="test"; 237 console.log(data.map(function(item,index,arr){return item*2;}));//[ 2, 4, 6, 8, 10 ] 238 console.log(data);//[ 1, 2, 3, 4, 5, test: 'test' ] 239 240 //filter()方法,对数组中的每一项运行给定函数,返回指定函数运行结果为true 的项组成的数组 241 //始末状态:不会改变数组本身 242 //参数:给定的函数 243 //函数参数:可以有3个参数,参数一:当前数组元素 参数二:当前元素索引 参数三:数组本身 244 var data=[1,2,3,4,5]; 245 data["test"]="test"; 246 console.log(data.filter(function(item,index,arr){return item%2==0;}));//[ 2, 4 ] 过滤出偶数 247 console.log(data);//[ 1, 2, 3, 4, 5, test: 'test' ] 248 249 //every()方法,对数组中的每一项运行给定函数,如果该函数对每一项都返回true,则返回true 250 //始末状态:不会改变数组本身 251 //参数:给定的函数 252 //函数参数:可以有3个参数,参数一:当前数组元素 参数二:当前元素索引 参数三:数组本身 253 var data=[1,2,3,4,5]; 254 data["test"]="test"; 255 console.log(data.every(function(item,index,arr){return item%2==0;}));//false 部分返回 true 256 console.log(data.every(function(item,index,arr){return item>0;}));//true 全部都返回 true 257 console.log(data);//[ 1, 2, 3, 4, 5, test: 'test' ] 258 259 //some()方法,对数组中的每一项运行给定函数,如果该函数对任一项返回true,则返回true 260 //始末状态:不会改变数组本身 261 //参数:给定的函数 262 //函数参数:可以有3个参数,参数一:当前数组元素 参数二:当前元素索引 参数三:数组本身 263 var data=[1,2,3,4,5]; 264 data["test"]="test"; 265 console.log(data.some(function(item,index,arr){return item%2==0;}));//true 部分返回 true 266 console.log(data.some(function(item,index,arr){return item>0;}));//true 全部都返回 true 267 console.log(data);//[ 1, 2, 3, 4, 5, test: 'test' ] 268 269 //reduce()方法,按照指定函数,迭代数组的每一项,然后返回一个构建的最终值 270 //始末状态:不会改变数组本身 271 //参数:参数一:执行简化操作的函数 参数二(可选):传递给函数的初始值,当没有改参数时会将数组的第一个元素作为初始值 272 //函数参数:可以有4个参数,参数一:当前为止累计操作的结果 参数二:当前数组元素 参数三:当前元素索引 参数四:数组本身 273 var data=[1,2,3,4,5]; 274 data["test"]="test"; 275 console.log(data.reduce(function(x,y){return x+y},10));//25 (即10+1+2+3+4+5的累加结果) 276 console.log(data.reduce(function(accumulative,item,index,arr){ 277 console.log("accumulative:"+accumulative); 278 return accumulative+item 279 }));//accumulative:1(数组第一个元素作为初始值) accumulative:3(1+2) accumulative:6(3+3) accumulative:10(6+4) ,15 (即1+2+3+4+5的累加结果) 280 console.log(data);//[ 1, 2, 3, 4, 5, test: 'test' ] 281 282 //reduceRight()方法,与reduce(),不过是按照索引从高到低运算 283 var data=[1,2,3,4,5]; 284 data["test"]="test"; 285 console.log(data.reduceRight(function(x,y){return x+y},10));//25 (即10+1+2+3+4+5的累加结果) 286 console.log(data.reduceRight(function(accumulative,item,index,arr){ 287 console.log("accumulative:"+accumulative); 288 return accumulative+item 289 }));//accumulative:5(数组最后一个元素作为初始值) accumulative:9(5+4) accumulative:12(9+3) accumulative:14(12+2) ,15 (即5+4+3+2+1的累加结果) 290 console.log(data);//[ 1, 2, 3, 4, 5, test: 'test' ] 291 292 293 //indexOf()方法,搜索整个数组中具有给定值得元素,返回找到的第一个元素的索引,没有找到则返回-1 294 //始末状态:不会改变数组本身 295 //参数:参数一:要搜索的元素(这里指有索引的元素,前面已经提过了) 参数二(可选):指定从哪个元素开始搜索,默认为0,负数表示从倒数第几个数开始 296 var data=[1,1,2,3,4,5,{},"str","str",6,7]; 297 data["test"]="test"; 298 console.log(data.indexOf(1),data.indexOf("str",-4),data.indexOf("test"));//0 7 -1 299 //解析:对于元素“1”,找到遇到的第一个“1”,返回该元素下标"0"。对于元素"str",从倒数第4个数(即从左往右的第一个“str”)开始搜索, 300 //找到遇到的第一个"str",返回该元素下标“7”。对于"test",由于这里是指有索引的元素,因此没有找到对应的元素,返回"-1" 301 302 //lastIndexOf()方法,与indexOf()方法类似,只不过搜索的方向是从数组尾部开始搜索 303 var data=[1,1,2,3,4,5,{},"str","str",6,7]; 304 data["test"]="test"; 305 console.log(data.lastIndexOf(1),data.lastIndexOf("str",-4),data.lastIndexOf("test"));//1 7 -1 306 //解析:对于元素“1”,因为是从尾部开始搜索,所以先遇到的是数组中的第二个"1",返回该元素下标"1"。 307 //对于"str"和“test"解析同上