小结(二)

173 阅读11分钟

数据类型转换

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

1.转字符串:2个

1、xx.toString();//xx不能是undefined和null,报错,两者不能使用.去操作
	2String(xx);//万能的,没用:完全等效于隐式转换,还不如+""
	一般来说两个都不用,页面上获取到的数据都是字符串

2、*转数字:3个

    1、字符串 to 数字:parseInt/Float(str);
	   从左向右,依次读取每个字符,碰到非数字字符就停止转换,如果一开始就不认识,则为NaN
	   Int不认识小数点,Float认识第一个小数点

	2Number(xx);//万能的,没用:完全等效于隐式转换,还不如-0 *1 /1 %1

3、转布尔:1Boolean(xx);//万能的,没用:还不如!!x
	***只有6个为false0""undefinednullNaNfalse,其余都为true
	一定不会手动使用此方法,但是在某些地方会自动带有此方法:
		1、分支条件
		2、循环条件
		以后不管我在分支条件和循环条件之中写的是什么,只需要管为true还是false

   隐式转换:一般都出现在运算符和表达式中

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

1、*算术运算符:+ - * / %

 隐式转换:默认转为数字,再运算
     特殊:1、+运算,只要碰上一个字符串,两边都会悄悄的转为字符串(悄悄调用了一个方法,我们程序员看不见String()),再拼接
	   2、- * / %,只要是纯数字组成字符串,也可以转为数字(悄悄调用了一个方法,我们程序员看不见Number())
               
           

2、*比较/关系运算符:> < >= <= == != === !==

返回的结果:布尔值:truefalse
    隐式转换:默认一切都转为数字,再比较大小
    特殊:1、如果参与比较【两个都是字符串】,按位pk每个字符的十六进制unicode号(十进制ASCII码)
		0-9<A-Z<a-z<汉字
	  	建议记忆:汉字第一个字:一:4e00(ascii码:19968)
			    最后一个字:龥:9fa5(ascii码:40869)
	  2NaN,参与任何比较运算结果都为false,解决:!isNaN(x)
		x是一个数字,结果true
		x是一个NaN,结果就为false
	  3undefined==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());
			}
		}
                    

3、*逻辑运算符:

    &&:全部条件都为true,结果才为true
    只要有一个为false,结果就为false

||:全部条件都为false,结果才为false
    只要有一个为true,结果就为true

 !:颠倒bool值

特殊:***短路逻辑:只要前一个条件已经可以得出最终结论,则后续条件不会再执行
	&&:如果前一个条件满足,则后一个操作才执行,如果前一个条件不满足,则后一个操作不执行
	    实现了一个【简单】的分支:目的:简化if(){},操作只能【用一句话】
	    语法:条件&&(操作);
	    举例:if(total>=500){total*=0.8}
		  total>=500&&(total*=0.8)

	||:两个值中二选一 - 老IE(6/7/8)兼容
	    现在不用特别管住,看代老师玩玩就行
                

4、位运算:

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

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

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

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

***鄙视/笔试题:++ii++ 的区别?
	1、单独使用时,放前放后无所谓都一样
	2、如果参与了别的表达式,变量中的值都会+1
		前++,返回的是加了之后的新值
		后++,返回的是加了之前的旧值
                    

6、*三目运算 - 简化if...else if...else if...else

如何使用:
  1、条件?操作1:默认操作;
  2、条件1?操作1:条件2?操作2:条件3?操作3:默认操作;

特殊:
  1、只能完成【简单】的分支 - 操作只能有一句话,其实以后很多分支里面可能真的就只有一句话
  2、默认操作不能省略 - 会报错

*****自定义函数:方法,一段提前被定义好的,可以反复使用的代码段

 1、如何使用:21、*创建/定义/声明函数&返回结果:21、*声明方式:用function关键字进行声明 - 并不是人人都有声明方式,只有个别人才有,而且声明方式一定是最简单的
		只有3个人具有声明方式:变量、常量、函数,其余人最简单的方式也是直接量
  function 函数名(形参,...){
			   函数体
			   return 返回值;
	        }
                    
         2、直接量方式:
		var 函数名=function(形参,...){
			   函数体
			   return 返回值;
	        }	
		函数名其实也是一个变量名	
 2、调用函数&接住结果
	var result=函数名(实参,...);
            
 解释:return:本意退出函数,但是如果后面跟着一个数据,则可以将数据返回到全局作用域中,但是仅负责返回,不负责保存,所以我们需要自己创建一个变量接住函数调用的结果
		 return只能写一次,而且最好写在函数体的后面
	 何时使用:并不是任何时候都需要加return1、全局想要使用局部的
			2、调用完函数还希望拿到函数的结果在后续还要做操作时
			3、如果没有return,其实也有默认返回值undefined
                            
                            
                            
                            
                            
                       

***作用域:2个

1、全局作用域:全局变量 和 全局函数,在任何位置都可以访问/使用

2、函数/局部作用域:局部变量 和 局部函数,只能在当前【函数调用时内部可用】

有了作用域才有变量的使用规则: 优先使用自己的,自己没有找全局,全局都没有报错

***强烈建议:千万不要对未声明的变量直接赋值,导致全局污染 所有的变量在使用之前都一定要先var,不能对着没有var变量直接赋值

***哪些属于局部变量:2部分

            1、直接在函数作用域中创建的变量
            
            2、形参

问题:全局无法使用局部的?不符合现实生活
解决:看上面 - 创建函数部分

3、***声明提前

在程序执行之前
悄悄将var声明的变量和function【声明】的函数
集中提前到当前作用域的顶部
但是赋值留在原地
变量比函数更轻

我们程序员是看不见的,但是会悄悄执行的

注意:只会在鄙视题遇到:自己写代码开发时绝对不会遇到
	1、你写代码的时候尽量要先创建后使用
	2、你写代码的时候尽量不要出现重复的名字

鄙视:如果你看到先试用后创建,多半都是考你声明提前
    

4、***按值传递:两个变量之间进行赋值

            1、如果传递的是原始类型的值:两个变量之间赋值,做操作,互不影响的 - 其实是复制了一个副本给对方

	2、如果传递的是引用类型的对象:Array、Function
		两个变量之间赋值,做操作,是会相互影响的 - 因为两个用的是同一个地址值

函数之所以能有5颗星:考点太多太多?
	1、创建函数的方式 - 3种?
	2、作用域带来了什么?变量的使用规则
	3、声明提前
	4、按值传递
	5、重载 
	6、闭包 
            
            

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

1、编码和解码:

 问题1:url网址中不允许出现多字节字符,如果出现会导致乱码(没人看得懂)
		utf-8编码格式下,一个汉字占3字节
           解决:前端工程师需要将用户输入的网址中的中文编码为单字节字符,后端工程师接住前端传来的东西解码为原文
	 编码:var code=encodeURIComponent("str");
	 解码:var 原文=decodeURIComponent(code);

	 以前有用,现在没用:随着浏览器的不断升级,浏览器现在自带此功能
             

2、isFinite(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
   

***循环结构:反复执行相同 或 像相似的操作

1. while循环:

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

2.do...while循环:

var 循环变量=几;
  do{
循环体;
变量变化;
}while(循环条件)


 面试题:whiledo...while的区别?
 只看第一次,如果第一次大家都满足条件,俩这没有区别,无非do...while更麻烦
 如果第一次大家都不满足条件,while一次都不会执行,而do...while至少会执行一次

3.***for循环:

 for(var 循环变量=几;循环条件;变量变化){
    循环体;
    }
    

4.循环终止语句:

*break-退出整个循环
continue-退出本次循环

*****数组的基础:一个变量可以保存多个数据

1.创建:2种方式

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

2.访问:

获取:arr[i];-特殊:下标越界:得到undefined
添加/替换:arr[i]=新值-特殊:下标越界:得到稀疏数组

3.*3大不限制:

不限制长度、类型、下标越界(不是好东西)

4.length的三个固定套路:

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

5.遍历数组:

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

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

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

7。**

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

创建:2步

1.创建一个空数组:var arr=[];
2.添加自定义下via哦并且赋值:arr["自定义"]=值

访问:arr["自定义下标"];

遍历:把所有的元素都取出来执行 相同 或者 相似的操作

问题:不能使用for循环,因为length失效了,关联数组永远为0,而且下标也不在是一个数字
解决:for in循环体:
for(var i in 数组名){
    数组名[i];
    }
  无敌:不光可以遍历关联数组,也可以遍历索引数组
  个人建议:索引数组依然使用for循环
      关联数组只能使用for in 循环
      

***JS中除了undefined和null不是一个对象,万物皆对象,而且一切对象的【底层都是hash数组】

hash数组的原理:

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

*****数组的API:函数:前辈们预定依好的,但是只有数组可以使用的方法

1.数组转为字符串:

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

特殊:

1.如果没有传入实参,则和to String/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.必须使用二位数组,而且二维数组的数据孙旭一定要和一级的对应上
 2.select专属事件:select.onchange:状态改变事件:选中项发生改变才会触发
 3.select具有一个属性:this.selectedlndex;获取选中项的下标-只有select不需要自定义下标
 4.其实绑定事件的部分就是函数名,也可以拿来调用
 

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

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

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

  var subArr=arr.slice(starti,endi+1)
  特殊:
  1.此方法不修改原数组,只会返回一个新数组
  2.含头不含尾
  3.第二个实参可以省略:从starti截到末尾
      第一个实参也可以省略:从头截到尾
  4.支持负数参数,-1代表倒数第一个
  

以上的3个API都不会修改原数组 ————————————————————————————————————————————————————————————————————————————————————————————— 以下的几个API都会被修改原数组

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();没用

*****Array API:

6.排序:两种方式

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.降序排序:
                        return a-b;
                        })
		//return b-a:如果a>b,返回是一个正数
                    //如果a<b,返回是一个负数
                  //如果a==b,返回是一个0,sort根据你反复的结果,来判断两者要不要交换位置

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

7、栈和队列: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();//一次只能删掉一个,并且会返回删除的元素
                    

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

*****String API:

1.转义字符:\

 作用:3个
 1.字符串中如果出现了和字符串冲突的符号,可以用\将其转义为原文
     \*
 2.特殊功能:
 换行:\n
 制表符:\t
 3.可以书写uniconde号表示一个字
 \uXXX
 汉字的第一个字:4e00
 汉字的最后一个字:9fa5
 

2.转换大小写:【统一的】转为大写或小写,在比较,忽略大小写:-验证码

     大写:var newStr=str.toUpperCase();
     小写:var newAtr=str=to.LowerCase();
     

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

 var ascii=str.charCodeAt(i);
 通过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、如果传入的切割符是一个"",每一个字符都会被切开
            

创建元素并且渲染页面

1、创建空标签
	var elem=document.createElement("标签名");

2、设置必要的属性或事件
	elem.属性名="属性值";
	elem.on事件名=function(){函数体} - 事件都可以在创建时提前绑定上

3、创建好的元素渲染到DOM树上
	父元素.appendChild(elem);