二阶段 第二周笔记01

111 阅读6分钟

一.数组的基础

1、创建数组:

	1、直接量:var arr=[值1,...];
	2、构造函数:var arr=new Array(值1,...);
            第二个方法有一个坑:new Array(num);//这句话的意思是:创建了一个
            长度为num的空数组,里面没有任何东西,只有无数的undefined.

2.按值传递:var a=x; var b=a; 修改a,b变不变,或者 修改b,a变不变

传递的如果是原始类型: 其实是复制了一个副本给对方,两者互不影响

传递的如果是引用类型: js中不是原始类型,就是引用类型(函数、数组,都是引用类型)- 浅拷贝

因为引用类型很大,比原始类型大得多,不可能保存在变量本地,只是保存了一个地址值而已,其实是赋值了自己的地址值给对方,两者用的是同一个地址值,一个修改另一个也会变化

3、如何释放一个引用类型:一定要看清楚有几个变量引用着这个引用类型,每个变量都要释放后才能释放干净 在js底层有一个垃圾回收器,只有垃圾回收器的计数器(记录着这个数据有几个人引用着)为0的时候才会删除不要的数据 建议:我们的代码都要封装为一个函数,函数中的一切变量都会自动释放

二.*****hash数组(重要):下标可以自定义

索引数组:下标都是数字组成的数组(索引数组的下标无具体的意义,不便于查找 ) hash数组:

1.创建:

1)、创建空数组:var arr=[];
2)、为数组添加自定义下标并且赋值:arr["自定义下标"]=新值;
    

2、访问元素:arr["自定义下标"];

3、强调:hash数组的length失效了,永远为0!

		遍历hash数组:必须使用for in循环 - 专门为了遍历hash数组存在的:
                    
                            for(var i in 数组名){
				i;//下标
				数组名[i];//当前次元素
			}
		不止能遍历hash数组,也能遍历索引数组
		建议:索引数组依然用forhash数组使用for in

4、hash数组的原理(重要):

hash算法:将字符串,计算出一个尽量不重复的数字(地址值) 字符串内容相同,则计算出来的数字也一定是相同的 添加元素:将自定义下标交给hash算法,得到一个数字(地址值),直接将你要保存的数据放到此地址保存起来 获取元素:将指定的自定义下标交给hash算法,得到一个和当初保存时一样的数字(地址值),通过此地址找到你当初保存的数据,取出来使用

5、js里面一切的东西都是对象,万物皆对象,除了undefined和null,【一切对象的底层都是hash数组】 学习这一块最大的目的:是为了对象做准备工作

三.*****数组的API:前辈们预定义了很多方法,只需要学会如何使用,就可以直接用上 - 这些方法只有(数组)可用

1、**arr 转 str: var str=arr.join("自定义连接符");

	固定套路:2个
		1、鄙视题:将数组里面的内容拼接为一句话/单词 - 无缝拼
                    接,其实就是拼接了一个空字符串
		var arr=["h","e","l","l","o"," 
                            ","w","o","r","l","d"];
			var str=arr.join("");
			console.log(str);

		2、将数组拼接为DOM页面元素 - 第一次遇到数据渲染页面
			//拿数据
			var arr=["-请选择-","北京","南京","西京","东
                            京","重庆","北京","南京","西京","东京","重
                            庆","北京","南京","西京","东京","重庆","北
                            京","南京","西京","东京","重庆","北京","南
                            京","西京","东京","重庆","北京","南京","西
                            京","东京","重庆"];
			//将数组拼接为页面标签字符串 
			var str="<开始标签>"+arr.join("</结束标签><开
                            始标签>")+"</结束标签>";
			//巧了:innerHTML能够识别标签
			sel.innerHTML=str;

2、**数组拼接:添加元素的新方式

	将你传入的实参全部拼接到arr的末尾
	var newArr=arr.concat(新值1,arr1,...);
	特殊:
		1、不修改原数组,只会返回一个新数组
		2、concat支持传入数组参数,悄悄的将你传入的数组打散为单个元素再拼接

3、**截取子数组:

	根据你传入的开始下标截取到结束下标
	var subArr=arr.slice(starti,endi+1);
	特殊:
            1、不修改原数组,只会返回一个新数组
		2、含头不含尾*
		3、endi可以省略不写,如果省略,会从starti位置一直截取到末尾
		4、starti也可以省略,如果两个实参都省略,那么会从头到尾
                    完全的复制一份:此操作也叫做深拷贝 - 复制了一个副本给对
                    方(修改副本,原文件不会变)
		5、支持负数参数,-1代表倒数第1个

------------上面的API不修改原数组,下面的都会修改原数组-------------------------

4、***删插替:

	删除:var dels=arr.splice(starti,n);//n代表删除的个数
	    特殊:虽然他直接修改原数组,但是也有返回值,返回的是被删除的
                数据组成的一个新数组,没有删除也会返回一个空数组
	插入:arr.splice(starti,0,新值,...);
	    特殊:1、原starti位置的元素以及后续元素都会向后移动
	         2、尽量的不要插入一个数组,会导致我们的数组一些是一维,
                     一些是二维,遍历的时候就非常不方便
	替换:var dels=arr.splice(starti,n,新值,...);
	    特殊:删除的个数和插入的个数不必相同

5、翻转数组:arr.reverse();作用不大;

6、数组排序:

            1、鄙视时:冒泡排序:前一个元素和后一个元素进行对比,
            如果前一个>后一个,两者就交换位置,
            但是做完一轮发现只有最大的一个数字到了最后,
            所以再开循环反复使用,固定公式:
		原始方法:var arr=             [31,21,54,4376,69,8,8,65,643,52,3,321,5,47,69,87,643,524];
	 for(var j=1;j<arr.length;j++){
	    for(var i=0;i<arr.length-j;i++){
		if(arr[i]>arr[i+1]){
		  var m=arr[i];
		  arr[i]=arr[i+1];
		  arr[i+1]=m
		}
	    }
	}
		console.log(arr);

2、排序API:arr.sort(); 默认:将数组中的元素转为字符串后,再按位PK每个字符的unicode号(ASCII码)

问题1:希望按照数字升序排列: arr.sort(function(a,b){//此函数叫做匿名回调函数,回调函数不需要我们程序员调用,由前辈们创建好,我们学习如何使用即可,其实前辈们的sort方法悄悄的帮助我们调用了

	        console.log(a);//后一个数字
		console.log(b);//前一个数字
		return a-b;//如果a-b返回的是一个正数:说明后一个>前一个
			  //如果a-b返回的是一个负数,说明后一个<前一个
			//如果a-b返回的是一个0,说明后一个==前一个
//而sort方法会根据你返回的正数、负数、0,来自动考虑要不要交换位置
		})

		问题2:希望按照数字降序排列:
			arr.sort(function(a,b){
				return b-a;
			})

强调:切记:1、以后只要网页上有功能带有排序,他的底层一定是数组,因为js中只有数组可以排序
       2、以后只要网页上有随机的功能,那么他的底层一定用到了随机数公式!

拓展:二级联动:

关键点:31select专属事件onchange - 只有在选中项发生变化后才会触发
2select专属属性selectedIndex - 获取到当前选中项的下标
3、必须使用二维数组再次细分每个分类 

7.栈和队列:添加元素和删除元素的新方式:

    栈:其实就是数组,只不过是一端封闭了,只能从另一端进出
何时:现实生活中,情况不多:电梯、旅游巴士... 优先使用最新的数据
    如何使用:
    
        开头进:arr.unshift(新值,...);//添加元素的新方式,向前添加,
        缺点:导致其余元素的下标都发生变化
        开头出:var first=arr.shift();//删除元素的新方式,向前删除,
        一次只能删除一个,缺点:导致其余元素的下标都发生变化
        结尾进:arr.push(新值,...);//添加元素的新方式,向后添加。
        结尾出:var last=arr.pop();//删除元素的新方式,向后添加。
        

     队列:其实就是数组,只不过一端进,从另一端出:
		开头进:arr.unshift(新值,...);
		结尾出:var last=arr.pop();

		结尾进:arr.push(新值,...);
		开头出:var first=arr.shift();

	ES3的数组的API你就算是学完了,ES5还提供了6个API等你们学习

8、二维数组:数组的元素,又引用着另一个数组

何时:在一个数组,希望再次细分每个分类
创建:
	var arr=[
		["预判",18,900],
		["王刘振",19,1000],
		["干湿唱",20,700]
	];
访问:arr[行下标][列下标];
特殊:列下标越界,返回undefined
          行下标越界,得到是一个报错,因为行下标越界已经得到一个
              undefined,undefined没有资格在加[]做操作

遍历二维数组:必然两层循环,外层循环控制行,内层循环控制列
		for(var r=0;r<arr.length;r++){
			for(var c=0;c<arr[r].length;c++){
				console.log(arr[r][c]);
			}
		}

9.ES5还提供了3组6个API:

1、判断:2个
	every:每一个,要求所有元素都满足条件才会为true,
            只要有一个不满足则为false,非常类似于我们的&&
		var bool=arr.every(function(val,i,arr){
			//val - 当前的值
			//i - 当前的值的下标
			//arr - 当前数组本身
			return 判断条件;
		})

	some:有一些,要求只要有一个元素都满足条件会为true,
            所有元素都不满足则为false,非常类似于我们的||
		var bool=arr.some(function(val,i,arr){
			return 判断条件;
		})

2、遍历:拿到数组中的每个元素做相同 或 相似的操作
	forEach - 直接修改原数组
		arr.forEach(function(val,i,arr){
			直接做你想要的操作;
		})

	map - 不修改原数组返回一个新数组
		var newArr=arr.map(function(val,i,arr){
			return 直接做你想要的操作;
		})

3、过滤和汇总:
	过滤:筛选出你需要的部分,但是和现实不一样的是原数组
            并不会发生变化
		var subArr=arr.filter(function(val,i,arr){
			return 判断条件;
	          	})

	汇总:
		var result=arr.reduce(function(prev,val,i,arr){
			return prev+val;
	          	},基础值)

	以上6个API都是在简化我们的for循环操作,
            以后数组我们可能真的不会再写for循环

ES6箭头函数:简化一切匿名回调函数的:
	固定公式:function去掉,()和{}之间添加=>,如果形参只有一个,
            那么()可以省略,如果函数体只有一句话,那么{}也可以省略,
            如果函数体只有一句话并且是return,那么return和{}都可以省略