第二周笔记整理
day6
一:数据类型转换
1、强制转换
1):转字符串:2种
a: xx.to String ——>undefined和null不能用
b: String(xx); ——>万能,不能用
2):转数字 3种
a: parseInt(str/num); ——>专门用于将数字字符串转为整数
b: parseFloat(str); ——>专门用于将字符串转为浮点数(小数)
c: Number(xx); ——>万能,不用
3):转布尔值
a: Boolean(x); ——>万能,不用
b: 哪些东西转为false? 6个
0,“ ”,undefined,Null,NaN,false 其余全为true。
if(Boolean(条件)){
};
while(Boolean(循环条件)){
};
2、隐式转换:都出现在运算符种
二:运算符和表达式
1、算术运算:+ - * / %
前面四个运算符和小时候一样
但是特殊:
a、%:取余,俗称模,两个数相除,但是不取商,而是取除不尽的余数
5%2 ==> 1
作用:
1、*判断奇偶性
num%2;//结果为0说明是一个偶数,结果为1说明是一个奇数
2、获取某个数字的最后n位
1234%10;//4
1234%100;//34
1234%1000;//234
b、自带隐式转换:悄悄地转换,数据类型会发生变化,我们程序员看不见
常理来说只有数字才能参与算术运算,但是其实字符串也可以,一定要切记下面的几句话
*****默认运算符左右两边都会悄悄转换为一个数字,再运算
特殊:
a、+运算,只要碰上一个字符串,则都会变为字符串,+运算也不再是+运算,变成了拼接操
b、-*/%运算:有字符串也可以转为数字,但是必须是纯数字组成的字符串才可以,只有包含一个非数字字符,结果则为NaN
NaN:Not a Number:不是一个数字,但是确实是数字类型 - 垃圾
NaN参与任何算术运算结果都为NaN
NaN参与任何比较运算结果都为false - 不在三界之中
以后不希望见到undefined和NaN
2、比较运算:>,<,>=,<=,==,!=,===,!== (结果为Boolean值)
特殊
a:如果左右两边参与比较都是字符串,则是按位PK每个字符的十六进制的unicode号(十进制ascii码)
0-9<A-Z<a-z<汉字
百度搜索:中文字符集Unicode编码范围
汉字第一个字:(Unicode:4e00,Ascii码:19968);
汉字最后一个字:龥(unicode:9fa5,Ascii码:40869);
b: NaN参与任何比较运算结果都为false,甚至不认识自己。
解决:
!isNaN(xx);true ——> 有效数字
false ——>NaN
c: undefined==null;
问题: ==区分不开undefined和null,如何区分?
解决: ===全等,要求值和数据类型都要相同,不再带有隐式转换的比较运算。
!==,不带有隐式转换的不等比较
3、逻辑运算符:
隐式转换:变为布尔值再综合比较
并且:&&:全部条件都满足位true,只要一个不满足就为false;
或者:||:全部条件都不满足位false,只要满足一个就为true;
!:颠倒布尔值,类似于数学中的负号。
特殊:用法
短路逻辑:只要前一个条件已经可以得到最后的结论,则后续条件不再执行。
&&短路:
简化了【简单的】分支结构:if(条件){操作};
语法:条件&&(操作);
举例:
曾经:if(total>=500){total*=0.8};
现在:total>=500&&(total*=0.8);
特殊:【简单的】 ——>操作只能有一句话
操作复杂的还是用if结构
||短路:
若前一个条件位true,则后面条件不看
若前一个条件位false,则后一个才看
使用:两个值二选一,后期可用做浏览器兼容问题
e=e||window.event;
4、位运算: 垃圾
5、赋值运算:一句话执行了两个操作,先运算,后赋值。 +=,-=,*=,/=,%=,++,--;
何时使用:只要取出变量中的值,再做运算,之后还要再保存回去时,就使用它。
递增:++;每次只能+1
累加:i+几;每次想加几,随便都可以。
鄙视题:++分为++i和i++。
a: 单独使用时,没有参与别的表达式,都一样
b: 如果参与了别的表达式:
变量中的值其实都会+1
++i,返回的都是递增后的【新值】;
i++,返回的都是递增前的【旧值】。
6、三目运算:
简化了if(){}else 和 if(){}else if(){}else
语法:1):条件?操作1:默认操作;
2): 条件?操作1:条件2?操作2:默认操作;
总结:
if(){} 用&&短路
if(){}else 用三目
if(){}else if(){}else 用三目
建议:能用三目或者&&短路尽量不用if
扩展:
1:舍入误差(可用作四舍五入)
num.toFixed(n); ——>n表示保留几位小数
此方法会使结果变为字符串,建议搭配parseFloat使用
2:获取第一个字符的ascii码:
var ascii=str.charCodeAt(0);
day7
一、自定义Function:
函数:需要先定义好,可以反复调用的一个代码段。
使用:
a: 不希望打开页面立刻执行
b:以后可以反复的使用
c:希望绑定再页面元素上
1:如何使用:
1) 创建:2种
a: 【声明方式】创建函数:
function 函数名 (形参1,形参2,...){
函数体;
return 返回值;
};
b: 【直接量方式】创建函数:
var 函数名=function(形参1,形参2,....){
函数体;
return 返回值;
};
2:调用
var 接住返回结果=函数名(实参1,实参2,...);
3:举例:
创建:function f1(){
console.log("我是f1");
};
调用:f1();
4:return
return的本意是退出函数,但是如果return后面跟着一个数据,顺便将数据返回到函数作用域的外部,
但是return只返回,不保存,具体要不要return,全看需不需要获得函数结果。return只能在函数内部使用。
二、作用域:2种
1:全局作用域:
全局变量和全局函数。
作用:在页面任何位置都可以使用。
2:函数/局部作用域:
局部变量和局部函数
特点:在【当前函数调用时,内部可以用】。
3:变量的使用规则:
优先使用自己的,自己没有找全局,全局没有就报错。
特点:缺点
1);千万不要在函数种对着未声明的变量直接赋值,会导致全局污染
解决:尽量变量使用前都先var一下
2):局部可以用全局的,但是全局不能用局部的
解决:搭配上return
4:声明提前 ——>鄙视题
在程序正式执行之前
将var声明的变量(轻)和function【声明的】函数(重)都会集中定义在【作用域的顶部】,但是都会将【赋值留在原地】。
【声明方式】创建的函数会【完整的提前】。
【直接量方式】创建的函数不会完整提前,只有【变量部分提前】。
都不会使用,只会在鄙视题种遇到,遵守以下几个规则:
a:变量名和函数名尽量不重复
b:先创建后调用
c:如果鄙视时,遇到先使用后创建,多半是考声明提前,先转换为我们认识的代码,再去判断。
5:按值传递:两个变量之前进行赋值
如果传递的是【原始类型】的值:修改一个变量,另一个变量不会受到影响。
如果传递的是【引用类型】的对象:修改一个变量,另一个变量也会受到影响,两者使用的是 同一个地址值(浅拷贝)。
三、预定义全局函数:
1:编码和解码:
问题:url中不允许出现多字节字符,如果出现就会乱码
utf-8编码格式下,一个汉字就是3字节字符
解决:发送前,前端将多字节字符编码为单字节字符(数字/字母)
发送后,后端将单字节字符解码为多字节原文。
如何:
编码:var code=encodeURIcomponent(str);
解码:var 原文=decodeURIcomponent(code);
2:isFinite(num):
判断num是不是无穷大:true ——>有效数字
false ——>无穷大
哪些为false?
NaN,Infinity,分母为0。
3:牛逼的: parseInt/parseFloat/eval/isNaN
四、分支结构: if分支/switch分支
1:switch语法:
switch(变量/表达式){
case值1:
操作1;
break;
case值2:
操作2;
break;
default:
默认操作;
}
特殊:
1:case的比较不带有隐式转换
2:问题:默认只要一个case满足后,会将后面所有的操作全部做完
解决:在每个case操作后面都加一个break;
3:有些地方可以不加break;
a: 最后一个操作default后面可省略;
b: 若中间多个条件,做的是一样的操作,也可省略;
if VS switch区别:
1:switch...case:
缺点:必须要知道结果后才能使用,不能作范围判断。
优点:执行效率相对较高。
2:if...else:
缺点:执行效率相对较低。
优点:可用作范围判断。
建议:
代码优化,尽量将if...else换成switch...case或者三目或者&&短路。
day8
一:循环结构
1、while循环:
1): var 变量名=几次;
while(循环条件){
循环体;
变量变化;
}; ——>一般用于不确定循环次数。
2): var 变量名=几次;
do{循环体;变量变化;}while(循环条件);
鄙视或者面试:
do...while和while的区别:
如果第一次都不满足,while什么都不执行,do...while至少会执行一次。
2、for循环:
for(循环变量;循环条件;变量变化){
循环体}; ——>明确循环次数
3、退出循环:
break; ——>退出整个循环
continue; ——>退出本次循环,根据需求来判断需不需要执行后面的循环。
二:数组的基础
1:概念:
含义:在一个内存(变量)中保存了多个数据的一个集合结构
何时:只要存储多个相关数据,都要用数组集中保存
作用:一个好的数据结构,可以极大提升开发效率
2:创建:2种
**a:直接量: var arr=[值1,值2,....];
b:构造函数: var arr=new Array(值1,值2,...);
缺点:var arr2=new Array(5);创建了一个长度为5的空数组,不用。
3:访问/调用:
console.log(arr[下标]); ——>下标的当前元素
遍历整个数组:
for(var i=0;i<arr.length;i++){
console.log(arr[i]);
};
特殊:
a:读取元素,下标越界 ——>返回为undefined
b: 添加元素,下标越界 ——>下标不连续,导致稀疏数组。
4:数组的三大不限制:
a:不限制长度;
b:不限制类型;
c:不限制下标越界。
5:数组的唯一属性:
数组名.length; 可以获取数组的长度。
3个固定套路:
1)末尾添加: arr.[arr.length]=新值;
2) 获取倒数第几个: arr[arr.length-几];
3)删除倒数n个: arr.length-=n;
6:遍历数组: 对数组种每个元素进行相同或者相似操作
for(var i=0;i<arr.length;i++){
console.log(arr[i]; ——>当前下标元素
};
7:如何释放一个引用类型:
看清楚这个引用类型的数据有几个变量引用着,每个变量都要释放后,才能释放干净。
建议:代码都要封装到一个函数种,函数中变量会自动释放。
8:索引数组
下标都为数字组成的数组。
关联(hash)数组:下标都可以自定义
hash使用:
1) 创建:2步
a: 创建空数组: var arr=[];
b: 为数组添加自定义下标并添加元素值: arr["自定义下标"]="新值";
2) 访问/调用:
console.log(arr["自定义下标"]);
强调:hash数组的length永久失效为0!!!
3) 遍历hash数组:
for(var i in arr){
console.log(arr[i];
};
建议:索引数组依然使用for循环,hash数组用for...in。
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,新值2,...);
特殊:
1): 不能修改原数组,只会返回一个新数组;
2): concat支持传入数组参数,悄悄的将你传入的数组打散为单个元素后拼接。
3:截取子数组:
根据你传入的开始下标,开始截取,一直到结束下标。
var subArr=arr.slice(starti,endi);
特殊:
1): 不修改原数组,返回一个新数组
2):含头不含尾 ——>解决:var subArr=arr.slice(starti,endi+1);
3):endi可以省略不写,会从starti位置一直截取到末尾;
4):其实两个实参都可以不写,从头截取到末尾(深拷贝),与之前按值传递(浅拷贝)不同。
4:删除、插入、替换:
删除:var dels=arr.splice(starti,n); //n表示删除的个数,删除几个的意思
特殊:
其实splice也有返回值,返回值时删除的元素组成的新数组。
插入:var dels=arr.splice(starti,0,值1,值2,...);
特殊:
1):插入新的元素会将原有的数组和后续元素挤到后面去;
2):插入也有返回值,只不过没有删除元素,因此为空数组;
3):千万不要插入一个数组,会变成一个部分二维数组。
替换:var dels=arr.splice(starti,n,值1,值2,...);
n代表删除的个数。
特殊:
删除的元素个数不必与插入的元素个数一致。
5:翻转数组:
arr.reverse(); ——>不用
四:二级联动:
1):select的专属事件:onchange; //状态改变事件:只有选中项发生变化才会触发
2):select的专属属性:selectdIndex; //直接获取当前选中项下标
3):必须用到二位数组(再次细分)。
day6
一:Array API:
1:排序:2种方法
鄙视时:手写冒泡排序
公式:
for(var j=1;j<arr.length;j++){
for(var i=0;i<arr.length-j;i++){
if(arr[i]>arr[i+1]){
var middle=arr[i];
arr[i]=arr[i+1];
arr[i+1]=middle;
}
}
}
console.log(arr);
2: 正式开发中:数组提供了排序的API
arr.sort();
问题1:默认将数据们转为字符串,按位PK每个字符的Ascii码,如果希望按照数字排序怎么办?
解决:
arr.sort(function(a,b){
console.log(a); //后一个数字
console.log(b); //前一个数字
return a-b; //如果return返回是个正数,那么说明后面比前面的大
//如果return返回是个负数,那么说明前面比后面的大
//如果return返回是0,那么说明前面后面一样大
//而sort方法就是根据你返回的数字来判断要不要交换位置
问题2:如何降序排列?
arr.sort(function(a,b){
return b-a;
});
强调:排序非常重要,只要以后网页有任何排序功能,它底层一定是一个数组,因为只有数组才可以排序。
3:栈和队列:添加元素和删除元素的新方式。
栈:其实就是一个数组,只不过一端封闭,只能从另一端进出的数组。
何时:优先使用最新的数据。
如何:
开头进:arr unshift(新值,...) //添加元素新方式,向前添加
//缺点:会修改其它元素的下标,不能传入数组
开头出:var first=arr.shift(); //删除元素新方式,向前删除,一次只能删除一个
//缺点:修改其他元素的下标。
*** 结尾进:arr.push(新值,...); //添加元素的新方式,向后添加
//完美替代了arr[arr.length]=新值 和 arr=arr.concat(新值),不能传入数组
结尾进:var last=arr.pop(); //删除元素新方式,向后删除一个,一次只会删除一个。
搭配使用:
开头进:arr.unshift(新值,...);
结尾进:var last=arr.pop();
*结尾进:arr.push(新值,...);
开头出:var first=arr.shift();
二:二维数组:数组的元素又引用着一个数组。
何时:在一个数组内,希望再次细分每个分类
创建:
var arr=[ ["张三丰",128,5500],
["张翠山",38,4500],
["张无忌",18,3500]
];
访问/调用:
arr[行下标][列下标];
特殊:
列下标越界,返回为undefined
行下标越界,报错
遍历二维数组:
必然两层循环,外层循环控制行,内层循环控制列。
for(var r=0;r<arr.length;r++){
for(var c=0;c<arr[r].length;c++){
console.log(arr[r][c]);
}
};
三:string的基础概念;
含义:多个字符组成的【只读】字符【数组】 ——>不会修改原字符串
1):和数组相同的地方:
a:字符串中的个数:str.length;
b: 获取字符串某个字符:str[i];
c:遍历字符串
d:所有数组不能修改原数组的API,字符串都能使用 ——>(concat(还不如+隐式转换拼接)、slice)。
2):和数组不同的地方:
所有数组直接修改原数组的API,字符串都不可以使用,比如排序只有数组可以使用
字符串也有很多属于自己的API
引用/对象类型:11个
String\Number\Boolean ——>它们三个拥有包装类型
*Array\*Function\Date\Math\*RegExp(正则:验证)\Error\*Object\Global(全局对象,在浏览器中被window对象给代替罢了)
包装类型:
含义:专门将原始类型的值封装为一个引用类型的对象
为什么:原始类型的值原本是没有任何属性和方法,本身不支持操作,为了方便我们对这个三个进行操作,提供了包装类型。
何时使用:只要试图用原始类型的变量调用属性和方法时,自动包装。
何时释放:方法调用完毕后,自动释放包装类型,并且返回数据。
undefined和null不能使用 ——>没有提供包装类型
扩展:
1:事件:onmouseover 鼠标移入
onmouseout 鼠标移出
2:开启定时器:
timer=setInterval(function){
操作
},间隔毫秒数);
3: 停止定时器:
clearInterval(timer);
day10
一:只读:
1、String API:可以直接使用,只有字符串才可以用
1):转义字符: \
作用:
a:将字符串中和程序冲突的字符转为原文
比如:双引号中还想放入双银行 "\""
b: 包含特殊功能的符号: ——>几乎没用
\n:字符串换行
\t: 制表符——大空格tab
*c: 输出unicode编码的字符——>搭配正则
\uxxx: 第一个汉字:\u4e00 ascii码:19968
最后一个汉字:\u9fa5 ascii码:40869
2、大小写转换:将字符串中每个英文字母统一转为大写或者小写
何时:只要程序不区分大小写,就要【先统一】的转为大写或者小写,再比较(验证码)
如何:
大写:var upper=str.to Uppercase();
小写:var lower=str.to Lowercase();
3、获取字符串中指定位置的字符。
var newStr=str.charAt(i) 还不如str[i]
4、获取字符串中指定位置的字符的ascii码
var ascii=str.charCodeAt(i); 搭配上循环,我们可以得到每一个字的ascii码
根据ascii码转回原文:
var 原文=String.from CharCode(ascii);
5、检索字符串,检查索引,获取关键字下标
var i=str/arr.indexOf("关键字",starti);
从starti位置开始,查找右侧【第一个关键字】的位置
starti可省略,默认从0位置开始查找
返回值:找到了,返回的是第一个关键字的第一个字符的下标
**没找到,返回-1,不关心下标为多少,只关心为不为-1
作用:以后只希望判断有没有或者不希望有重复的
强调:数组也能用此方法,老IE不支持
鄙视题:默认只能获取到第一个关键字的下标,如何才能获取所有关键字下标?
var i=-1;
while((i=str.indexOf("no",i+1))!=-1){
console.log(i);
};
6、截取子字符串:3种
**var subStr=str/arr.slice(starti,endi+1); //和数组用法一样
.substring(starti,endi+1); //用法几乎和slice相同,但不支持负数
.substr(starti,n); //支持负数,n代表截取几个数,不考虑含头含尾
7、拼接字符串
var newStr=str.concat("新字符串"); ——>不如+运算
8、*替换字符串
var newStr=str.replace("关键字"/RegExp,"新内容");
9、切割/分割字符串****
作用:将字符串转为数组
var arr=str.split("自定义切割符");
特殊:
a:切割后,切割符就不存在了
b:切割符是一个空字符串"",切散每一个字符
扩展:
1:创建元素:
var elem=document.createElement("标签名");
2: 为它设置必要的属性或者事件:
elem.属性名="属性值";
elem.onclick=function(){操作};
3:渲染到DOM树上/上树:
父元素:appendChild(elem);