Day5:数组的定义、遍历
一、数组
1、程序=数据结构(数据在程序中的存储结构)+算法 良好的数据结构可以极大的提高程序的执行效率
2、定义
存储:连续存储多个数据的存储空间
使用:相当于多个变量的集合
3、为什么要使用数组
因为现实中数组都是批量分类管理
何时使用:只要批量管理多个数据,就要用数组保存
如何使用:
(1)创建:数组都是用中括号([])创建出来的
var arr=[]; //创建一个数组对象,数组中包含0个元素
var arr=[34,45,33]; //创建了一个数组对象,数组中连续存储3个元素,34、45、33
数组的其他创建方式:(知道就行,一般不要用)
为什么不要用这种方式创建?
假设我让你创建一个数组,里面有一个元素,数字7
var arr=new Array(7) //这种是在堆中开辟7个存储空间
var arr=new Array('7') //创建一个字符串7
由此可得,这种方式容易让人产生歧义
var arr=new Array(num);
new:只要看到new,就是要在堆中开辟空间(var 栈中)
Array:ECMAScript标准中的内置类型
new Array:在堆中创建一个数组类型的存储区域
(num):初始创建num个元素
例如: var arr=new Array(7) //[undefined,undefined,undefined,undefined,undefined,undefined,undefined] 但是undefined在输出时会变为一个空字符
var arr=new Array(元素1,元素2,...元素n);
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> </head> <body> <script> var week=['日','一','二','三','四','五','六'];//中间用逗号分隔,最后一个不加逗号 //栈中创建一个变量,名为week //堆中创建一个大存储空间:地址可能是019x8 //栈中变量中存储的是地址019x8 //堆空间中存储的是实际数据 //week变量引用了堆中的一个数组对象 document.write(week+'<br/>'); var arr=new Array(7); document.write(arr+'<br/>'); var week1=new Array('日','一','二','三','四','五','六'); document.write(week1+'<br/>'); </script> </body> </html>
注:数组有两个不限制 1、不限制元素个数 2、不限制元素数据类型
数组是引用类型的对象: 1、原始类型:数据保存在变量本地 2、引用类型:数据不保存在变量本地,保存在‘堆’中,由地址指向实际数据,它的最大特点是:可以保存多个数据,而且数据个数随时可变 3、为什么要使用原始类型? 原始类型中只能保存1个值 一个值无法精确描述一个东西 现实中,都是用多个属性共同描述一样东西
对象:凡是存储在堆中的都是对象
使用引用类型的对象:使用变量,等效于使用对象的地址,使用对象地址等效于使用对象本身
数组对象支持直接输出对象内容
(2)null:一个变量,没有指向任何对象
何时使用null:主动释放对象,主动释放的对象不能被找回了
null vs undefined:
null:专用于主动释放对象
undefined:专用于自动初始化任何未赋值的变量
垃圾回收:js引擎自动销毁不再被引用的对象
垃圾回收程序:随js程序运行而后台同时运行,有延迟,只要对象还有变量引用,就不回收
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> </head> <body> <script> var week=['日','一','二','三','四','五','六'];//中间用逗号分隔,最后一个不加逗号 //栈中创建一个变量,名为week //堆中创建一个大存储空间:地址可能是019x8 //栈中变量中存储的是地址019x8 //堆空间中存储的是实际数据 //week变量引用了堆中的一个数组对象 document.write(week+'<br/>'); var day=week;//值传递:将内部数值赋值给新变量 week=['SUN','MON','TUS'];//新创建一个数组对象 //将新对象地址保存到原week变量中替换旧地址 //旧数组对象释放,等待垃圾回收 //week变量引用了新数组对象 </script> </body> </html>
4、访问数组:一组变量的集合
(1)如何获取其中一个变量/数据:下标
(2)下标:数组中唯一标识一个元素的序号,从0开始,数组最后一个元素的下标是 元素个数-1
如下:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> </head> <body> <script> var week=['日','一','二','三','四','五','六'];//中间用逗号分隔,最后一个不加逗号 //栈中创建一个变量,名为week //堆中创建一个大存储空间:地址可能是019x8 //栈中变量中存储的是地址019x8 //堆空间中存储的是实际数据 //week变量引用了堆中的一个数组对象 document.write(week+'<br/>'); var day=week;//值传递:将内部数值赋值给新变量 week=['SUN','MON','TUS'];//新创建一个数组对象 //将新对象地址保存到原week变量中替换旧地址 //旧数组对象释放,等待垃圾回收 //week变量引用了新数组对象 console.log(week[2]);//取出下标为2位置的变量 console.log(week[4]);//越界读取元素返回undefined,不会出错 </script> </body> </html>
(3)js内置对象不但封装存储,而且封装常用API
API:已经实现的方法,可以直接调用
(4)Array API
arr.length:属性(不能执行操作,但是能返回一个数,不加圆括号),数组的长度(元素的个数)
访问任意数组的最后一个元素:arr[arr.length-1]
length属性值,随数组长度变化而自动变化
js中数组可以根据程序的需要,自动扩容,保证程序正常执行,保证程序正常运行
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> </head> <body> <script> var week=['日','一','二','三','四','五','六']; week=[]; console.log(week.length);//0 week[0]='日' console.log(week.length);//1 week[2]='二' console.log(week.length);//3['日',undefined,'二'] week[4]='四' console.log(week.length);//5['日',undefined,'二',undefined,'四'] document.write(week);//日,,二,,四 </script> </body> </html>
(5)数组的扩容和缩容:
如果length属性值>旧值 ,会扩容,反之缩容(截断),被截断的元素不能被找到,不会被回收,只能随数组对象一起回收
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> </head> <body> <script> var week=['日','一','二','三','四','五','六']; week=[]; console.log(week.length);//0 week[0]='日' console.log(week.length);//1 week[2]='二' console.log(week.length);//3['日',undefined,'二'] week[4]='四' console.log(week.length);//5['日',undefined,'二',undefined,'四'] document.write(week+'<br/>');//日,,二,,四 week.length=7; console.log(week.length);//7 document.write(week+'<br/>');//日,,二,,四,, 扩容 week.length=3; console.log(week.length);//3 document.write(week+'<br/>');//日,,二 缩容 </script> </body> </html>
(6)在任意数组结尾追加一个新元素(固定用法):
arr[arr.length]=新值;
(7)练习题:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> </head> <body> <script> //不停录入员工姓名,知道输入exit退出,将这些姓名保存在一个数组中,控制台中输出所有元素 var input; var emps=[]; while(true){ input=prompt('输入姓名'); if(input!='exit'){ emps[emps.length]=input; }else{ break; } } document.write(emps); </script> </body> </html>
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> </head> <body> <script> //不停录入员工姓名,知道输入exit退出,将这些姓名保存在一个数组中,控制台中输出所有元素 var input; var emps=[]; //赋值同时用表达式的值做判断 while((input=prompt('输入姓名'))!='exit'){ emps[emps.length]=input; } document.write(emps); </script> </body> </html>
(8)
栈中的变量生命周期:和堆完全不同
var a=5; function fun(){ var b=10; } fun();//作用域环境栈 fun的作用域环境栈 出栈 fun的中局部变量一同消失 cosole.log(b) //refError 结论:局部变量的生命周期和所在方法的作用域环境栈有关 作用域创建,局部变量一同创建 作用域结束,局部变量一同消失
二、遍历数组元素
定义:对数组中的每个元素执行相同的操作
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> </head> <body> <script> var week=['日','一','二','三','四','五','六']; document.write(week+'<br>'); for(var i=0;i<week.length;i++){ week[i]='星期'+week[i]; } document.write(week); </script> </body> </html>
1、关联数组:数组下标可以自定义名称 key/value
(1)何时使用关联数组:数组元素内容无法描述自己的意义时,使用关联数组为每个元素起名
(2)for in:专门用来遍历关联数组用的,为什么不能用.length那种方法循环,因为length已经不能使用了
for(var key in arr){
//从第一个元素开始,将元素的key赋值给临时变量key
arr[key]-->当前正在遍历的元素的值(value)
}
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> </head> <body> <script> var fbb=[]; fbb['姓名']='李春雨'; fbb['年龄']=24; for(var key in fbb){ document.write(key+':'+fbb[key]+'<br>'); } </script> </body> </html>
(3)关联数组直接量定义方式:{‘key1’:'value1','key2':'value2'},必须使用大括号
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> </head> <body> <script> var fbb={'姓名':'李春雨','年龄':24}; for(var key in fbb){ document.write(key+':'+fbb[key]+'<br>'); } </script> </body> </html>
二、冒泡排序(还有一个是选择排序)
定义:冒泡排序法的具体实现方法是这样的,从数组的第一个元素`arr[0]`开始,两两比较(`arr[n],arr[n+1]`),如果前面的数大于后面的数(`arr[n] > arr[n+1]`),那么交换两个元素的位置,把大的数往后移动。这样依次经过一轮比较以后,最大的数将会被交换到最后的位置(arr[n-1])
1、算法:[3,5,2,6,7,9,8,4]升序
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> </head> <body> <script> //循环条件:当前元素下标<length-1 //循环变量:下标,从0开始 //循环体:当前元素>下一个元素 交换 var arr=[5,3,2,6,4,9,8,7]; //将最大数置换到最后一个元素 //从第一个数开始,依次取出每个元素和下一个数作比较 for(var n=1;n<=arr.length-1;n++){ for(var i=0;i<arr.length-n;i++){ var curr=arr[i]; var next=arr[i+1]; if(curr>next){//交换 var box=arr[i];//将i数据取出 arr[i]=arr[i+1];//将i+1的数据放入i arr[i+1]=box;//将取出的数据放入i+1 } } } console.log(arr); </script> </body> </html>
二、数组的常用方法
(1)x.toString()方法:任何对象都有toString方法,默认用逗号分隔每个元素,将任何对象转换成字符串,一般不主动调用,js在需要时自动调用
(2)x.valueOf()方法:同toString
(3)var str=arr.join('分隔符'):将数组转为字符串,可自定义分隔符
将字符拼接为单词或者句子 var chars=['h','e','l','l','o']; console.log(chars.join(''));//hello
(4)var newArr=arr.concat(元素值,[数组]):将参数拆散成单个元素追加到数组中,不会修改原数组,只能返回新数组对象
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> </head> <body> <script> var chars=[1,2,3]; var chars1=[12,33,323]; var newchar=chars.concat(chars1,99); document.write(newchar); </script> </body> </html>
(5)var subArr=arr.slice(start,end+1):截取数组下标从start开始,到end位置的元素,生成子数组对象
含头不含尾:如例子
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> </head> <body> <script> var chars=[1,2,3]; var chars1=[12,33,323]; var newchar=chars.concat(chars1,99); document.write(newchar+'<br>'); //截取下标位置为2开始到4之间的元素 var newchar2=newchar.slice(2,4+1); document.write(newchar2); </script> </body> </html>
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> </head> <body> <script> var chars=[1,2,3]; var chars1=[12,33,323]; var newchar=chars.concat(chars1,99); document.write(newchar+'<br>'); //截取下标位置为倒数2开始到倒数4之间的元素 //var newchar2=newchar.slice(newchar.length-4,newchar.length-2+1); var newchar2=newchar.slice(-4,-2+1); document.write(newchar2); </script> </body> </html>
(6)arr.splice:删除、插入、替换
删除数组元素:arr.splice(start,count);
替换数组元素:arr.splice(start,count,值1,值2....);
插入数组元素:arr.splice(start,0,值1,值2....);
返回每次被删除元素组成的新数组
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> </head> <body> <script> var chars=[1,2,3]; var chars1=[12,33,323]; var newchar=chars.concat(chars1,99); document.write(newchar+'<br>'); //newchar.splice(2,2); //删除 //document.write(newchar+'<br>'); //newchar.splice(2,2,77,88,99); //替换 //document.write(newchar+'<br>'); newchar.splice(2,0,33); //插入 document.write(newchar+'<br>'); </script> </body> </html>
(7)arr.reverse():颠倒数组所有元素
(8)arr.sort():默认升序排列,默认都转为字符串排序
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> </head> <body> <script> var chars=[22,1,2,3]; var chars1=[12,33,3]; var newchar=chars.concat(chars1,99); document.write(newchar+'<br>'); newchar.sort(); document.write(newchar+'<br>'); </script> </body> </html>