学JavaScript第二周

64 阅读6分钟

数据类型转换

1、转字符串:2种

1、`x.toString();`
2、`String(x);`
    

2、转数字:3种

    1parseInt(str/num);
    2parseFloat(str);
    3Number(x);

3、转布尔:

    `Boolean(x);`
    哪些东西会转为false6个:
    `0,
    "",
    undefined,
    null,
    NaN,
    false`
                   if(Boolean(条件)){

		}

		while(Boolean(循环条件)){

		}

短路逻辑:只要前一个条件已经可以得出最后结论,则后续条件不在执行: &&短路:如果前一个条件为true,则后一个操作才执行 如果前一个条件为false,则后一个操作不执行 简化【简单的】分支:if(条件){操作} 语法:条件&&(操作);

举例:`曾经:if(total>=500){total*=0.8}
     现在:total>=500&&(total*=0.8);

||短路:如果前一个条件为true,则后一个不看 如果前一个条件为false,则后一个才看 使用场景:两个值二选一 - 后期做浏览器的兼容性问题的

三目运算:简化了if(){}else if(){}else if(){}else

语法:
1、条件?操作1:默认操作;
2、条件1?操作1:条件2?操作2:默认操作;
    

舍入误差:

   语法:num.toFixed(n);

获取第一个字符的ascii码:

   var ascii=str.charCodeAt(0);

**自定义Function:

1、创建:2种
  *1、【声明方式】创建函数:
	function 函数名(形参,...){
		函数体;
		return 返回值;
	}

   2、【直接量方式】创建函数:
	var 函数名=function(形参,...){
		函数体;
		return 返回值;
	}

2、调用:

var 接住返回的结果=函数名(实参,...);

return的本意其实是退出函数,但如果return后面跟着一个数据 顺便将数据返回到函数作用域的外部,但是return只负责返回,不负责保存 就算你省略return,默认也会return undefined;

***作用域:2种

1、全局作用域:全局变量 和 全局函数,特点:在页面的任何位置都可以使用

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

导致变量的使用规则:优先使用自己的,自己没有找全局,全局没有就报错 特殊:缺点:

1、千万不要在函数中对未声明的变量直接赋值 - 导致全局污染,解决:尽量变量使用前都要记得先var一下

2、局部可用全局的,但是全局不能用到局部的

***声明提前:- 鄙视时

在程序正式执行之前 将var声明的变量(轻)和function【声明的】函数(重) 都会悄悄的集中定义在当前作用域的顶部 但是赋值留在原地

声明方式创建的函数会完整的提前(第一种) 直接量方式创建的函数不会完整的提前,只有变量部分会提前(第二种)

***按值传递:两个变量之间进行赋值 如果传递的是【原始类型】的值: 修改一个变量,另一个变量是不会受到影响的,其实是复制了一个副本给对方

如果传递的是【引用类型】的对象:

修改一个变量,另一个变量就会收到影响了,两者使用的是同一个地址值(浅拷贝)

编码和解码

	编码:var code=encodeURIComponent(str);
	解码:var 原文=decodeURIComponent(code);

isFinite(num):判断num是不是无穷大:true->有效数字 false->无穷大

	哪些会为false:NaN、Infinity、分母为0
	

***分支结构:根据条件选择部分代码执行:if分支 switch分支 语法:

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

特殊:1、case的比较不带隐式转换的 2、问题:默认只要一个case满足后,会将后面所有的操作全部做完 建议:每一个case的操作后都跟上一个break

   *面试题:if  vs  switch
	1switch...case:缺点:必须要知道结果才能使用,不能做范围判断
			  优点:执行效率相对较高

	2if...else:缺点:执行效率相对较低
		      优点:能做范围判断
                          

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

1、while(循环条件){循环体;变量变化;} - 不确定循环次数的时候

2、do{循环体;变量变化;}while(循环条件)

笔试/面试中:while 和 do...while的区别

只看第一次:如果第一次大家都满足,两者没有区别 如果第一次都不满足,while什么都不执行,do...while至少会执行一次

***for(循环变量;循环条件;变量的变化){ - 明确次数 循环体; }

*循环流程控制语句:退出循环:

break;//退出整个循环

continue;//退出本次循环,根据需求判断自己还需不需要执行后续的循环

*****数组的基础:

1、基础概念:
	什么是数组:在一个内存(变量)中保存了多个数据的一个集合结构
	何时:只要存储多个相关的数据,都要用数组集中保存

2、创建:2种
	1、*直接量:var arr=[值1,...];
	2、构造函数:var arr=new Array(值1,...); - 还有一个坑:var arr2=new Array(5);//创建了一个长度为5的空数组

3、访问:数组名[下标]; -- 当前元素
   添加/修改:数组名[下标]=新值;
   特殊:读取元素,下标越界 -- 返回undefined
	 添加元素,下标越界 -- 下标不连续,导致变成一个稀疏数组

4、数组的三大不限制:
	1、不限制长度
	2、不限制类型
	3、不限制下标越界

5、数组唯一的属性:arr.length; 获取到数组的长度

	三个固定套路:
		1、末尾添加:arr[arr.length]=新值;
		2、获取倒数第n个:arr[arr.length-n]
		3、删除倒数n个:arr.length-=n

6、遍历数组:对数组中的每个元素执行 相同 或 相似的操作:

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

7、*如何释放一个引用类型:清楚这个引用类型的数据有几个变量引用着,每个变量都要释放后,才能真正的释放干净

建议:我们的代码都要封装到一个函数中,函数中的变量会自动释放

8、索引数组:下标都是数字组成的数组
   关联(hash)数组:下标是可以自定义的
   为什么:索引数组的下标无具体的意义,不便于查找
   如何使用:
	1、创建:21、先创建一个空数组:var arr=[];
		2、为数组添加自定义下标并且添加元素值:arr["自定义"]=新值;

	2、访问:arr["自定义"]

	3、强调:hash数组length永久失效,永远为0!
	   遍历hash数组:不能使用for循环,必须使用for in循环 - 专门用于遍历hash数组准备的方式
		for(var i in arr){
			arr[i];
		}
	   for in虽然不能定义从哪里开始,到哪里结束,专门用于遍历hash数组的

4、***hash数组的原理:

		hash算法:将字符串,计算出一个尽量不重复的数字(地址值)
			  字符串内容相同,则计算出的数字也一定是相同的
		添加元素:将自定义下标交给hash算法,得到一个数字(地址值),把我的元素保存到了这个地址值之中
		读取元素:将指定的自定义下标交给hash算法,得到一个和添加时完全相同的数字(地址值),根据地址值找到之前保存的东西
	

5、*****js里面一切的东西都是对象:

除了undefined和null,【一切对象的底层都是hash数组】

*****Array的API:其实就是函数,只不过这些函数是前辈们提前定义好的,我们程序员可以直接使用的,这些方法只有数组可用

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

固定套路:
	  1、鄙视题:将数组中的内容拼接在一起形成一句话/单词;
		无缝拼接:var str=arr.join("");

	  2、将数组的元素拼接为DOM页面元素
		//数据
		var arr=["-请选择-","北京","南京","西京","东京","重庆"];
		//转为字符串,并且拼接好了标签
		var str="<option>"+arr.join("</option><option>")+"</option>";
		//渲染到DOM树上
		sel.innerHTML=str;

2、*数组拼接:添加新元素的新方式: 根据你传入的实参全部拼接到arr的末尾

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

3、*截取子数组: 根据你传入的开始下标截取到结束下标

	var subArr=arr.slice(starti,endi+1);
	特殊:1、不修改原数组,只会返回一个新数组
	      2、含头不含尾
	      3、endi可以省略不写,会从starti位置一直截取到末尾
	      4、其实两个实参都可以省略不写:从头截到尾:深拷贝:和以前的按值传递的浅拷贝不同,是复制了一个副本给对方,两者互不影响了

这条线以上的API都不会修改原数组

这条线以下的API都会修改原数组

4、*删除、插入、替换:

	删除:var dels=arr.splice(starti,n);//n代表删除的个数
	  特殊:其实splice也有返回值,返回的是你删除的元素组成的一个新数组
	插入:arr.splice(starti,0,值1,....);
	  特殊:1、插入新的元素会将原有元素和后续元素都推到后面去
		2、其实插入也有返回值,只不过没有删除任何元素则为一个空数组
		3、千万不要直接插入一个数组,会变成一个部分二维数组
	替换:arr.splice(starti,n,值1,...);
	  特殊:删除的元素个数不必和插入的元素个数一致

5、翻转数组:

           arr.reverse();

select的专属事件:onchange;//状态改变事件:只有选中项发生变化才会触发

select的专属属性:selectedIndex;//直接获取到当前选中项的下标

必须用到二维数组(再次细分)