一、数据类型转换(补充)
页面上拿到的数据都是字符串,有可能某些操作(+运算)不合适,需要我们去转换数据类型,再去做操作
强制类型转换
1.转字符串(2种)
a x.toString();
b.** String(x);**
2.转数字(3种)
a. parseInt(str/num) 专门用于将字符串转为整数的
执行原理:从左向右依次读取每个字符,碰到非数字字符停止,一来就不认识为NaN
b. parseFloat(str) 专门用于将字符串转为浮点数的
执行原理:几乎和parseInt一致,区别是它认识第一个小数点
c. Numbei(x); 万能的相当于隐式转换
2.转布尔
Boolean(x); 相当于隐式转换!!x
哪些转为false(6个)?
0,"",undefined,null.NaN,false
隐式类型转换
都出现在运算符之中
二、运算符和表达式(补充)
1.算数运算:+ - * / %
隐式转换:默认转为数字再运算
特殊:
a. +运算,只要碰上字符串就变为拼串操作
b. - * / %纯数字组成的字符串也可以转为数字但非纯数字则为NaN
NaN参与任何算数运算结果都为NaN
2.比较运算:> < >= <= == != === !==
结果:布尔值
隐式转换:默认左右两边转为数字再比较
特殊:
a.如果左右两边参与比较的都是字符串,则是按位pk每个字符的十六进制Unicode号(十进制ASCII码);
常识:0-9<A-Z<a-z<汉字
b. NaN参与任何比较运算,结果都为false,甚至不认识自己
c. undefined==null-->ture(==区分不开undefined和null)
===:要求值和数据类型都要相同,换句话说就是不再带有隐式转换的比较运算 !==:同上,不再带有隐式转换的不等比较
3.逻辑运算:
隐式转换:悄悄地都变为布尔值,然后再综合比较
&&
全部条件都满足结果为true,只要有一个条件不满足则为false
||
全部条件都不满足结果为false,只要有一个条件不满足则为true
!
颠倒布尔值
特殊:用法
短路逻辑:只要前一个条件已经可以得出结论,则后续条件不执行
&&短路:
如果前一个条件为true,则后一个操作才执行,如果前一个条件为法拉瑟,则后一个操作不执行
简化简单的分支,if(条件){操作}
语法:条件&&(操作);
例:
曾经:if(total>=500){total*=o.8}
现在:total>=500&&(total*=0.8)
||短路:
如果前一个条件为true,则后一个不看。如果前一个条件为false,才看后一个
使用场景:两个值2选1,后期浏览器兼容性问题
4.位运算:
左移:m<<n,读作m左移了n位,相当于m* 2的n次方
左移:m>>n,读作m左移了n位,相当于m/ 2的n次方
缺点:底数永远只能是2
5.赋值运算:+=,-=,*=,/=,%=,++,--
一句话执行了两个操作,先运算再赋值
何时使用:只要取出变量的值,再做运算,之后还要再保存回去时就用它
i=i+1-->i+=1-->i++
递增:i++,每次只能加1
累加:i+=n,每次相加n随便
++i和i++:
a. 单独使用时,没有参与别的表达式,放前放后都一样
b. 如果参与了别的表达式:变量的值都会加1,++i返回的是递增后的新值,i++返回的是递增前的旧值
6三目运算:
简化了if(){}else if(){}else if(){}else
语法:
条件?操作1:默认操作
条件1?操作1:条件2?操作2:默认操作
三函数(补充)
自定义Function
什么是函数:需要先定义好,可以反复调用的一个代码段
创建
1、声明方式创建函数
function 函数名(形参,...){
函数体;
返回值;
}
2、直接量方式创建函数
var 函数名=function(形参,...){
函数体;
返回值;
}
调用
var接住返回的结果=函数名(实参,...);
return的本意是退出函数,但如果return后面跟着一个数据,顺便将数据返回到函数作用域的外部,但return只负责返回不负责保存。就算省略不写return默认也会return undefined
四、作用域(2种)
全局作用域;
全局变量和全局函数,特点:在页面的任何位置都可以使用
函数(局部)作用域;
局部变量和局部函数,特点:在当前函数调用时内部可用
变量使用规则: 优先使用自己的,自己没有找全局,全局没有就报错
特殊:缺点: 千万不要在函数中对未声明的变量直接赋值--全局污染;局部可用全局的,但是全局不能用局部的,只能通过return来使用
五、声明提前
在程序正式执行之前
将var声明的变量(轻在上面)和function声明的函数(重在下面)都会悄悄地集中定义在当前作用域的顶部,但是赋值留在原地。
声明方式创建的函数会完整的提前,直接量方式创建的函数不会完整的提前,只有变量部分才会提前
六、按值传递:两个变量之间进行赋值
如果传递的是原始数据类型的值:修改一个变量,另一个不会受到影响,其实相当于复制了一个副本给对方
如果传递的是引用类型的对象:修改一个变量,另一个变量会受影响,两者使用的是同一个地址值(浅拷贝)
六、预定义全局函数:前辈们提前定义好的,直接调用,在哪儿都可用
1、编码和解码
编码:var code =encodeURLComponent(str);
解码: var 原文=decodeURLComponent(code);
2、判断是否无穷大
isFinite(num):true->有效数字;false->无穷大
重要的
parseInt/parseFloat/eval/isNaN
七、分支语句(switch)
语法:switch(变量/表达式){
擦色值1:
操作1;
break;
擦色值2:
操作2;
break;
default:
默认操作;
break;(可以不写)
} 特殊:a.case的比较不带隐式转换
b.问题:默认只要一个case满足后,会将后面的操作全部做完
解决:break;
八、循环结构(补充)
1、do{循环体;变量变化}while(循环条件)
和while区别:只看第一次,如果第一次都满足,两者没有区别,如果第一次都不满足,while什么也不会做,do while至少会执行一次
2、循环流程控制语句
退出循环:
break:退出整个循环
continue:退出本次循环,根据需求来判断还需不需要执行后续的循环
九、数组的基础
创建
1、直接量
var arr =[值1,...]
2、构造函数
var arr=new Array(值1,...);
坑:var arr=new Array(5);-->创建了一个长度为5的空数组
访问
数组名[下标];-->当前元素
添加/修改
数组名[下标]=新值
释放一个引用类型
看清楚这个引用类型有几个变量引用着,每个变量都要释放后,才能真正的释放干净
索引数组:下标都是数字组成的数组
关联(hash)数组:下表是可以自定义的
why?索引数组的下标无具体意义,不便于查找
创建关联数组
1、先创建一个空数组:var arr=[];
2、为数组添加自定义下标,并且添加元素值:arr["自定义"]=新值
访问关联数组
arr["自定义"]
hash数组length永久失效,永远为0
遍历hash数组
不能使用for循环,必须使用for in循环
for in循环
for(var i in arr){
arr[i];
}
js 里面一切的东西都是对象;除了undefined和null,一切对象的底层都是hash数组
十、Array的API
就是函数,是前辈们提前定义的,我们可以直接使用,这些方法只有数组可用
1、arr to string
var str=arr.join("自定义连接符");
固定套路
a.将数组中的内容拼接在一起形成一句话/单词
无缝拼接:var str=arr.join("");
b.将数组的元素拼接为DOM页面元素(数据渲染)
//数据
var arr=["-请选择-","重庆","四川"];
//转为字符串,并且拼接好标签
var str=""+arr.join("")+"";
//渲染到DOM树上
sel.innerHTML=str;
2、数组拼接:添加新元素的新方式
根据你传入的实参,全部拼接到arr的末尾
var newArr=arr.concat(新值1,...);
特殊:a.不修改原数组,只会返回一个新数组
b.concat支持传入数组参数,悄悄地将你传入的数组打散为单个元素后再拼接
3、截取子数组
根据传入的开始下标截取元素到结束下标
var subArr=arr.slice(starti,endi+1);
特殊:a.不修改原数组,只会返回一个新数组
b.含头不含尾(endi+1)
c.endi可以省略不写,会以starti位置一直截取到末尾
d.其实两个实参都可以不写,从头截取到尾(深拷贝)
4、删除、插入、替换
删除:var dels=arr.splice(starti,n);//n代表删除个数
特殊:其实splice也有返回值,返回的是你删除的元素,组成的一个新数组
插入:arr.splice(starti,0,值1,...);
特殊:a.插入新的元素会将原有元素后后续元素都推到后面去
b.插入也有返回值,只不过没有删除任何元素则为一个空数组
c.千万不要直接插入一个数组,会变成一个部分二维数组
替换:arr.splice(starti,n,值1,...);
特殊:删除的元素个数不必和插入的元素个数一致
5、翻转数组
arr.reverse();--大概不会使用