数组和各种API

131 阅读5分钟

数据类型的转换:两种;

一、显示转换:程序员主动调用函数完成的类型的转换:

1、转字符串:

1)tostring();前面的不能是undefinednull,会报错;
(2string();这个等于隐式转换,没什么大用

2、转数字:

1)字符串to数字:parseInt/Float(str);
从左向右,依次读取每个字符,碰到非数字字符就停止转换,
如果一开始就不认识,则为NaN,Int不认识小数点,Float认识第一个小数点;
 (2)Numder(XX):这个等于隐式转换,没什么大用

3、转布尔:

***只有6个为false0,“”,undefinednullNANfalse,其余的都是trueBOOleanXX):这个也是没什么用;我们不会手动使用此方法,有些地方会自动带有此方法:
  (1):分支条件;(2):分支循环;
     隐式转换一般都在运算符和表达式中;

****运算符和表达式:

一、*算术运算符:+-/*%;
 具有隐式转换:会默认转为数字在运算;
 +运算,只要碰上一个字符串,两边都会悄悄的转为字符串,在拼接,- * / %,只要是纯数字组成字符串,也可以转为数字;

二、比较/关系运算符:<,>,<=,>=,==,!=,===,!==;

返回的结果:布尔值:truefalse:具有隐式转换,会转为数字在比较大小;
特殊:(1)如果参与比较【两个都是字符串】,按位pk每个字符的十六进制unicode号(十进制ASCII码)0-9<A-Z<a-z<汉字;
(2):NAN,参与任何运算,结果都为false,可以使用!isNAN(x)来解决;
x是数字就是TRUE,是NAN就是false;
 (3):undefined==null:
问题:null==undefined结果为true,区分不开undefinednull
解决:全等===:数值相同 并且 数据类型也要相同,换句话说,不再带有隐式转换!==:不带隐式转换的不等比较
 //String()的执行原理:任何东西都可以转为字符串
function String(x){
	if(x===null){
	console.log("null");
        }else if(x===undefined){
            console.log("undefined");
	}else{
	console.log(x.toString());
	}
	}
            

*逻辑运算符;&&||!

 特殊:短路逻辑:只要前一个条件就能得到最终结论;则后续条件不会在执行;
&&:如果前一个条件满足,则后一个操作才执行,如果前一个条件不满足,则后一个操作不执行
实现了一个【简单】的分支:目的:简化if(){},操作只能【用一句话】
	    语法:条件&&(操作);
	    举例:if(total>=500){total*=0.8}
		  total>=500&&(total*=0.8)
||:两个值中二选一 - 老IE(6/7/8)兼容;

位运算:

左移:m<<n,读作m左移了n位,m*2的n次方 - 缺点:底数只能是2
右移:m>>n,读作m右移了n位,m/2的n次方 - 缺点:底数只能是2

*赋值运算:+= -= *= /= %= ++ --

 一句话完成了两个操作,先运算再赋值回去
 比如:i++ => i+=1 => i=i+1;

递增 vs 累加

递增:i++,每次只能加1
累加:i+=n,每次加几由我们自己决定

***笔试题:++i 和 i++ 的区别?

 1、单独使用时,放前放后无所谓都一样
 2、如果参与了别的表达式,变量中的值都会+1
    前++,返回的是加了之后的新值
后++,返回的是加了之前的旧值
    

三目运算:可以简化if...else........

 语法:  1、条件?操作1:默认操作;
   2、条件1?操作1:条件2?操作2:条件3?操作3:默认操作;	
   
例:
var weight = prompt('输入体重');
  var height = prompt('输入身高');
klt = weight / height / height;
console.log(
  klt <= 25 && klt >= 20 ? '正常体重' : klt < 20 ? '偏瘦' : '偏胖'
)

*****!自定义函数:也叫作方法,一段被提前定义好的可以被反复使用的代码; 如何使用:份两步;

*1、创建/定义/声明函数&返回结果:2种

   *1、声明方式:用function关键字进行声明,并不是所有的都有声明方式,只有个别人才有,而且声明方式一定是最简单的,只有三个人具有声明方式,变量常量和函数;其余的最简单的也是直接量:
function函数名(形参...){
        函数体
        return:}(返回值)
        

直接量方式:

var 函数名=function(形参...){
              函数体
        return:}(返回值)
        

调用函数&接住结果

var result=函数名(实参,...);

解释:return:本意退出函数,但是如果后面跟着一个数据,则可以将数据返回到全局作用域中,但是仅负责返回,不负责保存,所以我们需要自己创建一个变量接住函数调用的结果
return只能写一次,而且最好写在函数体的后面何时使用:并不是任何时候都需要加return1、全局想要使用局部的
2、调用完函数还希望拿到函数的结果在后续还要做操作时
3、如果没有return,其实也有默认返回值undefined

作用域:

一、全局作用域:全局变量和局部函数在任何位置都可以访问使用
 二、函数/局部作用域:局部变量和局部函数只能在当前函数调用是内部可以用
有了作用域才有变量的使用规则:
优先使用自己的,自己没有找全局,全局都没有报错
***:千万不要对未声明的变量直接赋值,导致全局污染
所有的变量在使用前一定要先var,不能对着没有var的变量直接赋值

***:局部变量有哪些:1、直接在函数作用域中创建的变量;2、形参

***声明提前

 在程序执行之前将var的变量和function声明的函数集中提前放到当前作用域的顶部,但是赋值留在原地,变量比函数更轻,我们看不见的,但是会悄悄执行;

面试的时候会在笔试题中可能碰到,开发中是没有的

  1、写代码的时候尽量先创建后使用
 2、写代码的时候尽量不要出现重复的名字
 如果笔试题中碰到先使用后创建,多半就是考声明提前的,
函数之所以难度太高,是因为他的考点很多很多;
            1、创建函数的方式 - 3种
	2、作用域带来了什么?变量的使用规则
	3、声明提前
	4、按值传递
	5、重载
	6、闭包 
            

预定义的全局函数:前辈们(实现浏览器的程序员们)提前定义好,我们可以直接在任何位置使用的函数:

1、编码和解码:
   问题1:url网址中不允许出现多字节字符,如果出现会导致乱码(没人看得懂)
		utf-8编码格式下,一个汉字占3字节
   解决:前端工程师需要将用户输入的网址中的中文编码为单字节字符,后端工程师接住前端传来的东西解码为原文
	 编码:var code=encodeURIComponent("str");
	 解码:var 原文=decodeURIComponent(code);
             
2isFinite(num):判断num是不是在有效范围之内
	三种情况会为false:分母为0,NaN,Infinity

3、重要的:parseInt/Float()、eval()、isNaN()

3、***分支结构:根据条件的不同,执行不同的操作 if...else结构 switch...case结构

语法:
  switch(变量/表达式){
	case1:
	操作1;
	break;
	case2:
	操作2;
	break;
	default:
	默认操作;
  }

注意:
  1、默认只要满足一条路,会把后面所有的操作全都做完,解决:break:一般放在操作的后面,但是:1、最后default不需要加break, 2、如果连续的多个操作是一样的效果,也可以省略中间部分
  2、不带有隐式转换
  3default可以省略不写

if vs switchswitch:优点:效率相对较高,因为不需要做任何范围判断
	        缺点:不能实现范围判断,必须要知道用户有可能输入的结果是什么才能使用
	if    :优点:实现范围判断
		缺点:效率相对较低

	个人建议:js优化,尽量的将if 优化为:三目、短路、switch
            

***循环结构(反复执行相同相似的操作)

 1while循环:
语法:var 循环变量=几;
      while(循环条件){
	循环体;
	变量变化;
      }

    2do...while循环:
语法:var 循环变量=几;
      do{
	循环体;
	变量变化;
      }while(循环条件)
          
          
    whiledo...while的区别?
	只看第一次,如果第一次大家都满足条件,两者没有区别,无非do...while更麻烦
	如果第一次大家都不满足条件,while一次都不会执行,而do...while至少会执行一次 
            
            
   3、***for循环:
for(var 循环变量=几;循环条件;变量变化){
	循环体;
}
    
   4、循环终止语句:
   *break - 退出整个循环
continue - 退出本次循环
    

*****数组的基础,一个变量可以储存多个数据 1、创建;

 1、直接量:var arr=[值,...]
 2、构造函数:var arr=new Array(值...);
 缺陷:面试中:new Array(3);设置一个长度为3的空数组
 

2、访问:

 获取:arr[i]:特殊,下标越界得到undefined
 添加/替换:arr[i]=新值:下标越界得到稀疏数组
 
 有三大不限制:长度,类型,下标越界(不是优点)
 

length的三个固定套路:

 获取数据的第n个元素:arr[arr.length-n];
 向末尾添加元素:arr[arr.length]=新值
 缩容:arr.length-=n;
 

遍历数组:

 for(var i=0;i<arr.length;i++){
             arr[i]://当前次元素
             }
             

特殊点:如何释放一个引用类型:

 要看清楚这个引用类型对象有几个变量名引用着,每个变量都要释放才能真的释放干净                
             

*新知识点:

 索引数组,下标都是数字组成的数组---默认
 关联(hash)数组:下标是可以自定义的数组
 自定义下标是因为索引数组的下标无具体意义,不方便查找
 

创建:2步;

 1、创建一个空数组,var arr=[];
 2、添加自定义下标并且赋值:arr ["自定义"]=值
 访问:arr[自定义]
 

遍历:for in循环:

 语法:for(arr i in 数组名){数组名[i]}
 这个操作很无敌,不光可以遍历关联数组,也可以遍历索引数组;
 建议就是:以后索引数组依旧使用for循环,关联数组只能使用for in循环
 

***js中除了undefined和null不是一个对象,万物皆对象,而且一切对象的底层都是hash数组 hash数组的原理:

  hash的算法,将字符串交给hash算法,会得到一个尽量不重复的数字,但是字符串内容相同的,那么得到的数字一定是相同的;
  添加元素:将自定义的下标交给hash算法,得到一个数字(地址值),把要保存的数据放到地址值中;
  获取元素:将指定的下标交给hash算法,得到一个和添加时完全相同的数字(地址值)得到这个地址值之中保存的数据了;
  

*****数组的API:函数:前辈们预定义的好的,但是只有数组可以使用的方法 1、数组 转为 字符串:

var str=arr.join("自定义连接符");
    

特殊: 1、如果没有传入实参,则和toString/String,完全一样,默认由,分割 2、固定套路:2个

      1、笔试题:提供一个数组给你,让你无缝拼接数组里面的内容变为一个字符串
		var arr=["h","e","l","l","o","                     ","w","o","r","l","d"];
		 var str=arr.join("")
		console.log(str);//"hello world";

   2、开发中:将数组中的数据拼接为页面上的元素:初级版数据渲染
		var cities=["北京","南京","西京","东京","重庆"];
		var str="<option>"+cities.join("</option><option>")+"</option>";
		sel.innerHTML=str;//innerHTML可以识别标签
                    

实现:二级联动:4个重点

1、必须使用二维数组,而且二维数组的数据顺序一定要和一级的对应上
2select专属事件:select.onchange:状态改变事件:选中项发生改变才会触发
3select具有一个属性:this.selectedIndex;获取选中项的下标 - 只有select不需要自定义下标
4、其实绑定事件的部分就是函数名,也可以拿来调用  
    

拼接数组:添加元素到的末尾的新方式

var newArr=arr.concat(值1,arr1...);
特殊:
  1、此方法不修改原数组,只会返回一个新数组
  2、此方法传参支持数组参数,并且会悄悄的打散这个数组,单独传入
      

截取子数组:从starti位置截取到endi+1位置的元素,组成一个新数组

var subArr=arr.slice(starti,endi+1)
特殊:
  1、此方法不修改原数组,只会返回一个新数组
  2、含头不含尾
  3、第二实参可以省略:从starti截到末尾
     第一实参也可以省略:从头截到尾 - 昨天按值传递(浅拷贝)
			深拷贝:复制了一个副本给对方
  4、支持负数参数,-1代表倒数第一个
      

4、删除、插入、替换:

删除:var dels=arr.splice(starti,n);//从starti开始删除n个
  特殊:此方法其实也有返回值,所有删除的元素组成的一个新数组

插入:arr.splice(starti,0,值1,...);//从starti开始删除0个,插入了新元素
  特殊:原来starti位置的元素以及后续元素都会被向后移动

替换:var dels=arr.splice(starti,n,值1,...);
  特殊:插入的个数和删除的个数可以随意

5、翻转数组:arr.reverse(); - 没用

目前的API:

    不能修改原数组的:var str=arr.join("自定义连接符");var newArr=arr.concat(值1,arr1...);var subArr=arr.slice(starti,endi+1)
    可以修改原数组的:删除:var dels=arr.splice(starti,n);插入:arr.splice(starti,0,值1,...);替换:var dels=arr.splice(starti,n,值1,...);翻转数组:arr.reverse();
    
    

*****Array API: 排序:两种方式:

	1、鄙视题:冒泡排序:把数组中的每一个数字取出来,前一个和后一个进行比较,如果前一个>后一个,两者就要交换位置:
		公式:
		var arr=[13,25,4,3675,12,23,3,215,2,1,42,4,65,473,2431,123];
		for(var j=0;j<arr.length-1;j++){
			for(var i=0;i<arr.length-(j+1);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();
		特殊:1、默认按照字符串按位PK每个字符的unicode号排序
		      2、按照数字排序:
				arr.sort(function(a,b){//回调函数:不需要我们程序员调用的函数:悄悄的带有循环,提供了两个形参:a是后一个数,b是前一个数
					return a-b;
				})

			//return a-b:如果a>b,返回是一个正数
			//	      如果a<b,返回是一个负数
			//	      如果a==b,返回是一个0,sort根据你反复的结果,来判断两者要不要交换位置

		      3、降序排列:
				arr.sort(function(a,b){//回调函数:不需要我们程序员调用的函数:悄悄的带有循环,提供了两个形参:a是后一个数,b是前一个数
					return b-a;
				})

	强调:JS中只有数组可以排序,以后我们见到网页上任何具有排序功能的案例,底层一定都是一个数组

栈和队列:4个API:添加元素和删除元素的新方式

	 栈:一端封闭,只能从另一端进出的操作
		开头进:arr.unshift(值1,...);
		开头出:var first=arr.shift();//一次只能删掉一个,并且会返回删除的元素
		  缺点:每一次进出都会修改其他人的下标
		
		结尾进:arr.push(值1,...);
		结尾出:var last=arr.pop();//一次只能删掉一个,并且会返回删除的元素
		  优点:不会影响到其他元素的下标

	 队列:只能从一端进入,另一端出:
		开头进:arr.unshift(值1,...);
		结尾出:var last=arr.pop();//一次只能删掉一个,并且会返回删除的元素

		结尾进:arr.push(值1,...);
		开头出:var first=arr.shift();//一次只能删掉一个,并且会返回删除的元素
                    
                    

二维数组:数组中的值再次引用了一个数组

何时使用:在一个数组内在此细分内容 例:

1、创建:
var arr=[
	["张三丰",128,3500],
	["张翠山",30,4500],
	["张无忌",18,5500]
];

2、访问:arr[r][c];
   特殊:面试中:
	 列下标越界:返回undefined
	 行下标越界:报错:undefined不能使用[]

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

*****String的概念:明天我们就可以学习String API - 概念很重要 string:字符串:多个字符组成的【只读】字符【数组】 1、为什么字符串也可以叫数组呢?

	和数组有共同点:
		1、支持下标 - 获取某个字符
		2、支持length - 字符的长度
		3、遍历
		4、数组不修改原数组的API,字符串也可以使用(concat、slice)

	不同点:数组修改原数组的API,字符串都不可以使用,但是字符串也有很多属于自己的API(明天)

2、只读:字符串中的所有的API都不会修改原字符串,只会返回新字符串

3、***引用类型的对象:11个

	String(字符串) Number(数字) Boolean(布尔) - 具有包装类型
	Array(数组) Function(函数) Math(数学) Date(日期) RegExp(正则) Error(错误) Object(面向对象)
	Global - 全局对象:在浏览器端被window对象给代替了:window对象可以省略不写出来

	包装类型:将原始类型的值变为一个引用类型的对象
	  为什么:前辈们发现字符串/数字/布尔经常都会被拿来使用,所以提前提供了包装类型封装为一个引用类型的对象,提供我们一些属性和方法(便于程序员操作)
	  何时使用:只要在你试图用原始类型的值去调用属性或者方法时,会自动套上包装类型
	  何时释放:属性或方法调用完毕后,包装类型自动释放
	  
	为什么undefinednull不能使用.:不具有包装类型,没有任何的属性和方法
            
            

【只读】字符数组:字符串的任何API都不会修改原本字符,保存新字符串;

*****string API 1、转字符串:
作用三个:

     1、字符串中如果出现了和字符串冲突的符号,可用\将其转义为原文
		\"	\'

	  2、特殊功能:
		换行:\n
		制表符:\t

	  3、*可以书写unicode号 表示一个字
		\uXXXX
		汉字的第一个字:4e00
		汉字的最后一个字:9fa5        
                    

2、*转换大小写:【统一的】转为大写或小写,再比较,忽略大小写:

	大写:var newStr=str.toUpperCase();
	小写:var newStr=str.toLowerCase();

3、获取字符串中指定位置的字符的ascii码

	var ascii=str.charCodeAt(i);

   通过ascii码转回原文
	var 原文=String.fromCharCode(ascii);

4、*检索字符串:检查索引/下标:从starti位置开始找右侧的第一个关键字的下标

	作用:判断有没有
	var i=str/arr.indexOf("关键字",starti);
	特殊:1、starti可以省略,如果省略则从0开始
	      2、返回值:找到了,返回第一个字符的下标
			 ***没找到,返回-1,其实我们根本不关心下标是几,只关心下标是不是-1,-1代表没找到,不是-1代表找到了
	      3、数组也可以使用此方法
	      4、鄙视题:找到所有关键字的位置
			var str="no zuo no die no can no bibi";
			var i=-1;
			while((i=str.indexOf("no",i+1))!=-1){
				console.log("找到了:"+i);
			}

5、拼接字符串:var newStr=str.concat(str1,str2...) 还不如 +运算

6、*截取字符串:3个

	1、**var subStr=str/arr.slice(starti,endi+1);
	2、var subStr=str.substring(starti,endi+1);//不支持负数参数
	3、*var subStr=str.substr(starti,n);//截取的个数,不必考虑含头不含尾

7、*替换字符串:

	var newStr=str.replace("关键字"/正则表达式,"新内容");

8、*****切割/分割字符串:作用:str <=> arr

	var arr=str.split("自定义切割符");
	特殊:
	1、切割符可以自定义,切割过后返回一个数组,数组中不再包含切割符
	2、如果传入的切割符是一个"",每一个字符都会被切开