数据类型的转化
转布尔:
Boolean(x):任何都可以转布尔,只有6个会为false:0,"",undefined,null,NaN,false
比较运算符:>,<,>=,<=,==,!=,===,!==;
结果:布尔值; 默认转化为数字再比较大小; 如果参与比较的左右两边都是字符串,则按位pk每个字符的16进制unicode; 0-9<A-Z<a-z<汉字; 常识:汉字的第一个字:一:unicode号为4e00,ascii号为19968; 最后一个字:龥:unicode号为9fa5,ascii号为40869;
===和==的区别
===不仅数值相同,数据类型也要相同; !==:不带有隐式转化的不等比较
逻辑运算符
&&
全部满足才满足,一个不满足则不满足
||
全部不满足才不满足,一个满足则满足
!
颠倒布尔值
短路逻辑
如果前一个条件已经可以得出最终结论,那么没有必要看后续
&&短路:条件&&(操作);
如果一个条件满足才执行后一个操作,如果前一个条件不满足则不管后续操作
||短路:e||window.event
实现浏览器兼容问题,二选一
位运算
左移:m<<n :m*2的n次方;右移:m>>n:2/2的n次方;底数只能为2,虽然可以设置幂,但不能设置底数
赋值运算
i++:递增每次固定加一;i+=1:累加,每次固定加几可以改变
i++和++i的区别
单独使用时,放前放后无所谓,效果一样 但是如果参与了别的表达式,变量中的值都会+1 前++:【返回的是加了过后】的新值; 后++:【返回的是加了过前】的旧值;
三目运算
效果等同于if
语法
条件1?操作1:默认操作; 条件1?操作1:条件2?操作2:默认操作
特殊
1、默认操作不能省略,省略后会报错; 2、如果操作有多句话,还是推荐使用if分支,多句操作再同一行不方便以后维护
计算机带有摄入误差
num.toFixed(d):d代表保留的小数位数,会四舍五入运算;返回的是字符串,需要用parseFloat
获取字符串的第一个字符的ascii码
str.charCodeAt(0)2
自定义函数
声明方式
function 函数名(形参列表){ 函数体; return 返回值; }
直接量方式
var 函数名=function(形参列表){ 函数体; return 返回值; }
return
return的本意:退出函数;return后面跟着一个数据,会将其返回到全局作用域中,只返回不保存,需要用变量接住;调用函数:var result=函数名(实参列表);
作用域
全局作用域
全局变量和全局函数,在任何地方都可以使用
函数/局部作用域
局部变量和局部函数,在函数调用时内部可用
变量的使用规则
优先使用局部的,局部没有找全局,全局没有就报错
特殊
1:不要对着未声明的变量直接赋值:a=1,会导致全局污染; 2:局部的东西全局不能使用; 3:哪怕没有写return,其实最后也有return值,只不过是一个return undefined; 4:return一般只会出现在函数的最后,而且只能出现一个;
声明提前
在程序正式执行之前,会悄悄地将var声明的变量和function声明的函数,集中提前到当前作用域的顶部,变量比函数轻 但是赋值留在原地
按值传递
两个变量之间进行赋值,如果传递的是原始类型的值:修改一个变量,另一个变量是不会受到影响到,其实是复制了一个【副本】给对象;如果传递的是引用类型的对象:修改一个变量,另一个变量其实也会受到影响,因为大家操作的其实是同一个【地址值】 - 浅拷贝
预定义全局函数
编码
var code=encodeURIComponent("内容");
解码
var 原文=decodeURIComponent(code);
判断无穷大
isFinite(num):true->有效数字,false->无穷大;NaN、Infinity、分母为0都会为false
switch分支
语法: switch(变量/表达式){ case 值1: 操作1; break; case 值2: 操作2; break; default: 默认操作; }
特殊
1:case的比较不带隐式转换的;2:只要一个case满足后,会将后面所有的操作全部做,所以需要加上break;3:default可以省略不写,如果条件都不满足的情况,则什么事都不会执行
面试:if和switch比较
switch:好处:执行效率相对较高,缺点:必须要知道最后的结果才能使用,case不能做范围判断; if:好处:可以做范围判断,缺点:执行效率相对较低; 开发时:用哪个都无所谓, 代码优化:尽量的将if换成switch
do while循环
var 循环变量=几; do{ 循环体; 循环变量的变化; }while(循环条件)
do while循环和while的区别
只看第一次: 如果第一次大家都满足,两者其实没区别; 如果第一次大家都不满足。while一次都不会执行,而do...while至少会执行一次
终止循环语句
break:退出整个循环 continue:退出本次循环,还会继续做下一次
关联(hash)数组
下标是可以自定义的数组
创建
1、先创建一个空数组:var arr=[]; 2、添加自定义下标并且赋值:arr["自定义下标"]=新值;
访问
arr["自定义下标"];
遍历关联数组
for in 循环
不能设置从哪里开始到哪里结束,所有的操作都是自动的
语法
for(var i in 数组名){ i;//自动得到每一个洗标 数组名[i];//当前hash数组中的元素了 } 既可以遍历hash数组,也可以遍历索引数组
关联(hash)数组原理(面试)
【hash算法】:将字符串交给hash算法,会得到一个尽量不重复的数字,但是字符串的内容相同,那么得到的数字也一定是相同; 【添加元素】:将自定义下标交给hash算法,得到一个数字(地址值),把要保存的数据放进去了; 【读取元素】:将指定的自定义下标交给hash算法,得到一个和添加时完全相同的数字(地址值),通过这个地址值可以拿到当初保存的东西;
Api数组转字符串
var str=arr.join("自定义连接符");如果没有传入实参,则和toString效果一致,默认都是用,隔开
面试:完成无缝拼接
var arr=["h","e","l","l","o"," ","w","o","r","l","d"]; console.log(arr.join(""));
将数组元素拼接为页面元素(数据渲染)
1:【获取数据】 var arr=["-请选择-","北京","南京","西京","东京","重庆"]; 2:【将数组转为了字符串,并且拼接上了标签】 var str=""+arr.join("")+""; 3:【让字符串上DOM树,innerHTML是识别标签】 sel.innerHTML=str;
实现:二级联动:4个关键点
【1】、必须使用二维数组,细分每一个城市,并且二维数组的顺序要和之前的一维数组对应 【2】、select.onchange=function(){} - 状态改变事件:只有选中项发生变化时,才会触发 【3】、select可以直接获取当前选中项的下标,而不需要自定义下标:select.selectedIndex; 【4】、其实绑定事件,等号左边部分就是你的函数名
Api拼接数组
var newArr=arr.concat(值1,arr2....);
特殊
【1】此方法不会修改原数组,必须拿一个变量去接住结果(返回的一个新数组); 【2】哪怕拼接的是一个数组,悄悄的打散数组,单个添加;
Api截取子数组
var subArr=arr.slice(starti,endi+1);
特殊
【1】此方法不会修改原数组,必须拿一个变量去接住结果(返回的一个新数组) 【2】含头不含尾 【3】如果只传入了一个实参,则为从starti开始,到末尾 【4】如果两个实参都省略,则复制了一份 - 深拷贝!两者互不影响 【5】支持负数参数,-1代表倒数第一个,-n代表倒数第n个
Api删插替
splice:
删除
var dels=arr.splice(starti,n);从starti位置开始删除n个元素;返回的是你删除的元素组成的数组
插入
var dels=arr.splice(starti,0,新值1,....);原来starti位置的元素以及后续元素都会被向后移动;没有删除元素,也有返回值,返回的是一个空数组而已
替换
var dels=arr.splice(starti,n,新值1,....);var dels=arr.splice(starti,0,新值1,....);删除的个数 和 插入的个数不必相同
Api翻转数组
arr.reverse(); 仅仅只能翻转
Api排序
arr.sort():默认转为字符串,按位PK每个字符的unicode(ascii)
升序
arr.sort(function(a,b){return a-b;}):a是后一个数,b是前一个数;如果a>b,就会返回一个正数,说明后一个数>前一个数;如果a<b,就会返回一个负数,说明后一个数<前一个数;如果a==b,就会返回一个0,说明后一个数==前一个数;而sort的底层就能通过你返回的值来判断要不要帮你交换位置
降序
arr.sort(function(){return b-a;})
手写冒泡排序
for(var j=1;j<arr.length;j++){ for(var i=0;i<arr.length-j;i++){ if(arr[i]>arr[i+1]){ var m=arr[i]; arr[i]=arr[i+1]; arr[i+1]=m; } } }
Api栈和队列
添加元素和删除元素的新方式
栈
一端封闭,只能从另一端进出
队列
只能一端进入,另一端出
栈:开头添加
arr.unshift(新值,....)
栈:开头删除
var first=arr.shift():一次只能删除一个,而且一定是删除的第一个元素;开头进出,会导致每个元素的下标都会发生变化
栈:结尾添加
arr.push(新值,...);
栈:结尾删除
var last=arr.pop();一次只能删除一个,而且一定是删除的最后一个元素
队列的使用
队列:以上4个API是可以混搭的; 开头入:arr.unshift(新值,....); 结尾出:var last=arr.pop(); 结尾入:arr.push(新值,...); 开头出:var first=arr.shift();
二维数组
数组的元素,又一次引用了一个数组
语法
var peoples=[ ["吴飞华",18,"洪兴"], ["冯伟朕",19,"东英"], ["封永跃",20,"三联"] ];
访问
arr[r][c] - r代表行下标,c代表列下标:【1】列下标越界,返回undefined【2】行下标越界,返回报错,因为行下标越界已经得到undefined再加[]则报错
遍历
固定公式:外层循环遍历行,内层循环遍历列: for(var r=0;r<peoples.length;r++){ for(var c=0;c<peoples[r].length;c++){ console.log(peoples[r][c]) } }
String的基础概念
多个字符组成的【只读】字符【数组】!
【只读】
字符串所有的API都不会修改原字符串,只会返回新的字符串
【数组】
跟数组有相同点:【1】字符串可以使用下标获取某个字符【2】字符串可以使用length获取字符的长度【3】字符串可以遍历得到每个字符【4】字符串可以使用数组不修改原数组的API(concat、slice)【5】所有数组直接修改原数组的API,字符串都不可以使用
JS内置对象(引用类型):11个
String Number Boolean -> 包装类型;Array Function Date(日期) Math(数学) RegExp(正则:验证);Error(错误);Object(面向对象);Global(全局对象)
包装类型
专门封装原始类型的值,将原始类型悄悄的变成了引用类型的对象(属性和方法)
为什么
前辈们觉得比如字符串经常会被我们拿来做一些操作,为了方便我们程序员,提供了包装类型,把字符串变成了一个对象,提供了我们一些操作字符串的属性和方法;【本身原始类型的值】,不带有任何属性和方法,意味着不能使用.去做操作的;为什么undefined和null不能使用.,他们俩没有提供过包装类型(没有任何属性和方法)
何时使用
只要你试图使用.去操作原始类型的值的时候,包装类型就会悄悄出现
何时释放
方法一旦调用结束,包装类型就会自动释放