第二阶段JavaScript第二周心得总结
今天结束了第二周的学习,因为假日的原因,这周只有三天的学习时间。虽然只有短短三天的学习时间,但是学习的知识内容还真不少,需要理解记忆的不少,需要熟记背诵的知识点也不少。所以任务也挺繁重的,所以今天来温习总结一下这周所学知识点。
DAY1
一、*** 数据类型的转换:
1.强势类型转换:
转字符串:2种
①x.toString()//undefined和null不能使用;不能用于调用方法。
②String(x);//万能的,但是不用,相当于隐式转换,还不如+"";
2.* 转数字:3种
①* parseInt(str/num)-专门用于将字符串转为整数。
执行原理:从左往右依次读取每个字符,碰到非数字字符则会停止,以来就遇到不认识的就为NaN。如undefined,null等。
②* parseFalot(str);-专门讲字符串转换为浮点数。
执行原理:几乎和parseInt一样,但是认识第一个小数点。
③Number(x);//万能的,但没什么用,不用,相当于隐式转换,还不如- * / %;
3.转布尔:Boolean(x);//万能的,但是没有用,不用,相当于隐式转换,还不如!!x;
- 哪些东西会转为false? 6个:0,"",undefined;null,NaN,false,其余的全部都为true;
注意:一定要记住哪些会转为false,非常有用!在【循环或分支的条件判断中】,不管你写的是什么,都会悄悄地隐式转换为布尔值。
if(Boolean(条件)){
}
while(Boolean(循环条件)){
}
隐式类型转换:都出现在运算符之中,哪怕不用console.log,也知道最会的结构是什么。
二、*** 运算符和表达式:
1.* 算术运算:+- * / %;
隐式转换:默认,转为数字,在运算;
特殊:1.+运算,只要碰上一个字符串,则变为拼接;
2.- * / % ,纯数字组成的字符串也可以转为数字,但是非纯数字字符串则为NaN。NaN参与任何算术运算结果都为NaN。
2.* 比较运算:> < >= <= == != === !==;
结果:布尔值
隐式转换:默认,左右两边都会悄悄的转换数字,再比较
特殊:1.如果左右两边参与比较的都是字符串,则是按照PK每个字符的是十六进制的unicode号(十进制ascii码);
切记:0-9<A-Z<a-z<汉字
汉字:记不了,太多了,20000+个以上,汉字一定比数字、英文大
百度搜索:中文字符集 Unicode 编码范围
汉字的第一个字:一(unicode:4e00,ASCII码:19968);
汉字的最后一个字:龥(unicode:9fa5,ASCII码:40869);
2.NaN参与任何比较运算结果都为false,甚至不认识自己,解决:!isNaN(x
);true->有效数字;false->NaN;
3.undefined==null;
问题:==区分不开undefined和null,怎么才能区分开?
全等:===,要求值和数据类型都要相同,就是不再带有隐式转换的比较运算。
!==,不带有隐式转换的不等比较。
3.* 逻辑运算符:
隐式转换:悄悄地转换为布尔值,然后再综合比较。
&&:全部条件都满足,结果为true;只要一个条件不满足,则为false。
||:全部条件都不满足,结果为false;只要一个条件满足,则为true。
!:颠倒布尔值。
特殊:用法
*** 短路逻辑:只要前一个条件已经可以得出最后结论,则后续条件不再执行:
&&短路:
如果前一个条件为true,则后一个操作才执行;
如果前一个条件为false,则后一个操作不再执行。
简化【简单的】分支:if(条件){操作}
语法:条件&&(操作);
举例:曾经:if(total>=500){total*=0.8}
现在:total>=500&&(total*=0.8);
特殊:1.【简单的】->操作只能有一句话
建议:简单的操作可用&&短路代替,但是操作如果复杂还是建议使用if。
||短路:如果前一个条件为true,则后一个不看。
如果前一个条件为false,则后一个才看。
使用场景:两个值二选一---后期做浏览器的兼容性问题的。
e=e||window.event;
4.位运算:垃圾。
左移:m<<n,读作m左移了n位,相当于m* 2的n次方
右移:m>>n,读作m右移了n位,相当于m/2的n次方缺点:底数永远只能是2
5.* 赋值运算:一句话执行了两个操作,先运算,再赋值。
+= -= *= /= %= ++ --;
何时使用:只要取出变量中的值,在做运算,之后还要在保存回去时,就是用它
i=i+1;//比较low的写法
推荐:
i+=1 或者 i++;
递增:i++; 每次只能+1
累加:i+=n; 每次想加几,随便你
- 鄙视题:++分为++i和i++;
1.单独使用时,没有参与别的表达式,放前放后都一样。
2.如果参与了别的表达式:
变量中的值其实都会加1.
++i,返回的是递增后的【新值】
i++,返回的是递增前的【旧值】
6.* 三目运算:简化了if(){}else if(){}else if(){}else;
语法:
1.条件?操作1:默认操作;
2.条件1?操作1:条件2?操作2:默认操作;
问题:1.只能简化简单的分支结构 - 三木操作也只能有一句话,不怕,其实以后你会发现很多if结果中操作恰巧只有一句话
2、默认操作是不能省略的 - 哪怕条件都不满足,至少还要做一件事
总结:
if(){} == &&短路
if(){}else == 三目
if(){}else if(){}else == 三目
建议:能用三目/短路尽量不要用if分支。
扩展:1、舍入误差:电脑很笨,计算能力某些情况很差,计算不清,js提供了一个方法:num.toFixed(n);//n代表保留的小数位数,根据你放入的小数位数自动四舍五入
//此方法有一个小缺陷:结果会变成一个字符串,建议搭配上parseFloat使用
计算机:很笨,但是很快,记忆力很棒(机械硬盘(永久保存)、固态硬盘(10年))
2、获取第一个字符的ascii码:
var ascii=str.charCodeAt(0);
DAY2
一、*** 自定义Function:
什么是函数:需要先定义好,可以反复调用的一个代码段
何时使用:1、不希望打开页面立刻执行 2、以后可以反复的使用 3、希望绑定在页面元素上
1、如何使用:
1.创建:2种;
- 1、 【声明方式】创建函数;
function 函数名(形参,...){
函数体;
return返回值;
}
2、【直接量方式】创建函数:
var 函数名=function(形参,...){
函数体;
return返回值;}
2、调用: var 接住返回的结果=函数名(实参,...); 注意: 1.return的本意其实是退出函数,但如果return后面跟着一个数据。
2.顺便将数据返回到函数作用域的外部,但是return只负责返回,不负责保存。
3.就算你要省略return,默认也会return undefined;
4.具体要不要return,全看你需不需要获得函数的结果。
5.往往预定义的函数底层都有一句return操作。
2、*** 作用域:2种;
1.全局作用域:全局变量 和 全局函数,特点:在页面的任何位置都可以使用。
2.函数/局部作用域:局部变量 和 局部函数,特点:在【当前函数调用时内部可用】。
导致变量的使用规则:优先使用自己的,自己没有找全局的,全局没有就报错。
特殊:缺点;
1.千万不要在函数中对未声明的变量直接赋值-导致全局污染,解决:尽量变量使用前都要记得先var一下;
2.局部可用全局的,但是全局不能用到局部的,-解决:看上面,搭配return。
3、*** 声明提前:-鄙视题;
在程序正式执行之前,将var声明的变量(轻)和function【声明的】函数(重)都会悄悄地集中定义在当前作用域的顶部,但是赋值留在原地。
声明方式创建的函数会完整的提前(第一种);
直接量方式创建的函数不会完整的提前,只有变量部分会提前(第二种);
何时使用:永远不会使用,垃圾干扰我们的判断。
只要遵守一下规则:
1.变量名和函数名尽量不要重复;
2.先创建后使用;
3.如果鄙视时,遇到先试用后创建的,多半都是在考你声明提前,先转换为我们认识的代码,再去判断。
4、*** 按值传递:两个变量之间进行赋值;
如果传递的是【原始类型】的值;
修改一个变量,另一个变量是不会受到影响的,其实是复制了一个副本给对方。
如果传递的是【引用类型】的对象:
修改一个变量,另一个变量就会收到影响了,两者使用的是同一个地址值(浅拷贝)。
2、预定义全局函数:前辈们提前定义好的方法,我们可以直接调用。
1、编码和解码:
问题:url中不允许出现多字节字符,如果出现会乱码。
utf-8编码格式下,一个汉字就是三字节。
解决:发送前,前端将多字节字符为单字节字符(数字、字母);
发送后,后端将多字节字符解码为多字节原文。
如何:
编码:var code=encodeURIComponent(str); 解码:var 原文=decodeURIComponent(code);
其实这个东西在某次浏览器更新后,就当场淘汰了,浏览器
自带此功能了
2. IfFinite(num):判断num是不是无穷大:true->有效数字;false->无穷大;哪些会为false:NaN、Infinity 、分母为0;
3.* 牛逼的:parseInt/parseFalot/eval/isNaN;
3、*** 分支结构:根据条件选择部分代码执行:if分支 switch分支;
语法:
switch(){
case 值1:
操作1;
break;
case 值2:
操作2;
break;
default:
默认操作;
}
特殊:1、case的比较不带隐式转换的
2、问题:默认只要一个case满足后,会将互殴面所有的操作全部做完
解决:break;
建议:每一个case的操作后都跟上一个break;
有的地方可以不加break;
1.最后的一个操作default可以省略break。
2.如果中间多个条件,做的操作是一样的,也不需要。
3.default可以省略,如果条件都不满足的话,什么事都不会做到。
*面试题:if vs switch
1、switch...case:缺点:必须要知道结果才能使用,不能做范围判断 优点:执行效率相对较高
2、if...else:缺点:执行效率相对较低
优点:能做范围判断
建议:代码优化,尽量将的if...else 换成 switch...case 或 三目 或 短路
DAY3
一、*** 循环结构:反复执行 相同 或 相似的操作:
1.whlie(循环条件){循环体;变量变化;}-不确定循环次数的时候。
2.do{循环体;变量变化;}while(循环条件);
鄙视/面试中:while和do...while的区别
只看第一次:如果第一次大家都满足,两者没有区别。
如果第一次都不满足,while什么都不执行,do...whlie至少会执行一次。
3.*** for(循环变量;循环条件;变量的变化){-明确次数
循环体;
}
4.* 循环流程控制语句:
退出循环:break;//退出整个循环。
continue;//退出本次循环,根据需求判断自己还需不需要执行后续的循环。
2、*** 数组的基础:
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、创建:2步;
1、先创建一个空数组:var arr=[];
2.访问:arr["自定义"];
3.强调:hash数组length永久失效,永远为0!。
遍历hash数组:不能使用for循环,必须使用for in循环-专门用于遍历hash数组准备的方式,
for(var in arr){arr[i];}
for in虽然不能定义从哪里开始,到哪里结束,专门用于遍历hash数组的。
个人推荐:索引数组依然使用for循环,hash数组字在用 for in。
4、*** hash数组的原理:
hash算法:讲字符串,计算出一个尽量不重复的数字(地址值)
字符串内容相同,则计算出的数字也一定是相同的。
添加元素:将自定义下标交给hash算法,得到一个数字(地址值),把我的元素保存到了这个地址值最之中。
读取元素:将制定的自定义下标交给hash算法,得到一个和添加时完全相同的数字(地址值),根据地址值找到之前保存的东西。
5、*** js里面一切的东西都是对象:除了undefined和null,【一切对象的底层都是hash数组】
三、*** Array的API:其实就是函数,只不过这些函数是前辈们提前预定好的,我们可以直接使用的,这些方法只有数组可用。
1.* arr to string:
varstr = 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(start i ,end i +1);
特殊:1.不修改原数组,只会返回一个新数组。
2.含头不含尾。
3.end i 可以省略不写,会从start i 位置一直截取到末尾。
4.其实两个实参都可以省略不写:从头截到尾:深拷贝:和以前的按值传递的浅拷贝不同,是复制了一个副本给对方,两者互不影响。
以上的API都不会修改原数组。
一下的API都会修改原数组。
4、* 删除、插入、替换:
删除: var dels=arr.splice(start i ,n);//n代表删除的个数。
特殊:其实splice也有返回值,返回的是你删除的元素组成的一个新数组。
插入:arr.splice(start i ,0,值1,...);
特殊:1.插入新的元素会将原有元素和后续元素都推到后面去。
2.其实插入也有返回值,只不过没有删除任何元素则为一个空数组。
3、千万不要直接插入一个数字,会变成一个部分二维数组。
替换:arr.splice(starti,n,值1,...);
特殊:删除的元素个数不必和插入的元素个数一致。
5.翻转数组:arr.reverse();-不会使用。
1、二级联动:
1、select的专属事件:onchange;//状态改变事件:只有选中项发生变化才会触发
2、select的专属属性:selectedIndex;//直接获取到当前选中项的下标
3、必须用到二维数组(再次细分)